Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

send-ranges

rexxars454MIT5.0.0TypeScript support: included

Express middleware for handling HTTP range requests

byteranges, multipart, multi-part, range

readme

send-ranges

npm version

Express middleware for handling HTTP range requests. Requires node 18 or higher.

Installation

npm install --save send-ranges

Usage

const path = require('path')
const fse = require('fs-extra')
const express = require('express')
const sendRanges = require('send-ranges')
const app = express()

const mp3Path = path.join(__dirname, 'mp3s')

async function retrieveFile(request) {
  const filename = request.params.filename
  if (!/\.mp3$/.test(filename)) {
    return null // Falsey values will call the next handler in line
  }

  const filePath = path.join(mp3Path, filename)
  const getStream = (range) => fs.createReadStream(filePath, range)
  const type = 'audio/mpeg'
  const stats = await fse.stat(filePath)

  return {getStream, type, size: stats.size}
}

app.get('/:filename', sendRanges(retrieveFile), (req, res) => {
  // If we got here, this was not a range request, or the `retrieveFile` handler
  // returned a falsey value
  res.sendFile(path.join(mp3Path, req.params.filename))
})

app.listen(3000, () => {
  console.log('Example app listening on port 3000!')
})

Options

Exported function accept an options config object that will be passed to range-parser. In addition that, this options object accept some send-ranges specific ones:

Pre-send hook

You can pass a beforeSend function as an option. This is handy if you want to:

  • Handle the response sending yourself
  • Use metadata fetched in the file retriever to set headers on the response
  • Validate and possibly cancel the response before it is sent

The retrieveFile function can return an additional metadata property which will be passed to the beforeSend function. Here's an example:

async function retrieveFile(request) {
  const file = await someObjectStore.getFile(request.path)
  const size = file.size
  const metadata = file.metadata
  const type = metadata.contentType
  const getStream = (range) => file.createReadStream(range)
  return {getStream, size, metadata, type}
}

async function beforeSend(info, cb) {
  const {request, response, metadata, sourceStream} = info
  response.set('Last-Modified', new Date(metadata.updated).toUTCString())
  cb()
}

app.get('/*', sendRanges(retrieveFile, {beforeSend}))

Maximum number of ranges

By default, up to two ranges are allowed. The limit can be adjusted with the maxRanges option:

sendRanges(retrieveFile, {maxRanges: 4})

intersectRanges

Optional function that allow to modify the list of ranges to be returned. This can be used for example if the data is not fully available because your file has holes in it. It will be called with an object with the same metadata field used for the beforeSend() optional function, and a ranges field with the list of ranges.

License

MIT © Espen Hovlandsdal

changelog

📓 Changelog

All notable changes to this project will be documented in this file. See Conventional Commits for commit guidelines.

5.0.0 (2023-09-28)

⚠ BREAKING CHANGES

  • ship with official typescript types
  • require node 18 or higher

Features

  • require node 18 or higher (1cea745)
  • ship with official typescript types (e7a0d75)

Change Log

All notable changes will be documented in this file.

4.0.0 - 2020-07-16

BREAKING

  • Drop support for Node 8.

3.0.0 - 2019-03-23

BREAKING

  • Drop support for Node 6.

2.0.0 - 2018-10-05

BREAKING

  • Vary: Range is no longer sent on 206 responses. As long as a cache behaves correctly on a 206 response (according to RFC 2616), this should be a safe (and more correct) behavior.