3 [![NPM Version][npm-version-image]][npm-url]
4 [![NPM Downloads][npm-downloads-image]][npm-url]
5 [![Linux Build][travis-image]][travis-url]
6 [![Windows Build][appveyor-image]][appveyor-url]
7 [![Test Coverage][coveralls-image]][coveralls-url]
9 Send is a library for streaming files from the file system as a http response
10 supporting partial responses (Ranges), conditional-GET negotiation (If-Match,
11 If-Unmodified-Since, If-None-Match, If-Modified-Since), high test coverage,
12 and granular events which may be leveraged to take appropriate actions in your
13 application or framework.
15 Looking to serve up entire folders mapped to URLs? Try [serve-static](https://www.npmjs.org/package/serve-static).
19 This is a [Node.js](https://nodejs.org/en/) module available through the
20 [npm registry](https://www.npmjs.com/). Installation is done using the
21 [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
29 <!-- eslint-disable no-unused-vars -->
32 var send = require('send')
35 ### send(req, path, [options])
37 Create a new `SendStream` for the given path to send to a `res`. The `req` is
38 the Node.js HTTP request and the `path` is a urlencoded path to send (urlencoded,
39 not the actual file-system path).
45 Enable or disable accepting ranged requests, defaults to true.
46 Disabling this will not send `Accept-Ranges` and ignore the contents
47 of the `Range` request header.
51 Enable or disable setting `Cache-Control` response header, defaults to
52 true. Disabling this will ignore the `immutable` and `maxAge` options.
56 Set how "dotfiles" are treated when encountered. A dotfile is a file
57 or directory that begins with a dot ("."). Note this check is done on
58 the path itself without checking if the path actually exists on the
59 disk. If `root` is specified, only the dotfiles above the root are
60 checked (i.e. the root itself can be within a dotfile when when set
63 - `'allow'` No special treatment for dotfiles.
64 - `'deny'` Send a 403 for any request for a dotfile.
65 - `'ignore'` Pretend like the dotfile does not exist and 404.
67 The default value is _similar_ to `'ignore'`, with the exception that
68 this default will not ignore the files within a directory that begins
69 with a dot, for backward-compatibility.
73 Byte offset at which the stream ends, defaults to the length of the file
74 minus 1. The end is inclusive in the stream, meaning `end: 3` will include
75 the 4th byte in the stream.
79 Enable or disable etag generation, defaults to true.
83 If a given file doesn't exist, try appending one of the given extensions,
84 in the given order. By default, this is disabled (set to `false`). An
85 example value that will serve extension-less HTML files: `['html', 'htm']`.
86 This is skipped if the requested file already has an extension.
90 Enable or diable the `immutable` directive in the `Cache-Control` response
91 header, defaults to `false`. If set to `true`, the `maxAge` option should
92 also be specified to enable caching. The `immutable` directive will prevent
93 supported clients from making conditional requests during the life of the
94 `maxAge` option to check if the file has changed.
98 By default send supports "index.html" files, to disable this
99 set `false` or to supply a new index pass a string or an array
104 Enable or disable `Last-Modified` header, defaults to true. Uses the file
105 system's last modified value.
109 Provide a max-age in milliseconds for http caching, defaults to 0.
110 This can also be a string accepted by the
111 [ms](https://www.npmjs.org/package/ms#readme) module.
115 Serve files relative to `path`.
119 Byte offset at which the stream starts, defaults to 0. The start is inclusive,
120 meaning `start: 2` will include the 3rd byte in the stream.
124 The `SendStream` is an event emitter and will emit the following events:
126 - `error` an error occurred `(err)`
127 - `directory` a directory was requested `(res, path)`
128 - `file` a file was requested `(path, stat)`
129 - `headers` the headers are about to be set on a file `(res, path, stat)`
130 - `stream` file streaming has started `(stream)`
131 - `end` streaming has completed
135 The `pipe` method is used to pipe the response into the Node.js HTTP response
136 object, typically `send(req, path, options).pipe(res)`.
140 The `mime` export is the global instance of of the
141 [`mime` npm module](https://www.npmjs.com/package/mime).
143 This is used to configure the MIME types that are associated with file extensions
144 as well as other options for how to resolve the MIME type of a file (like the
145 default type to use for an unknown file extension).
149 By default when no `error` listeners are present an automatic response will be
150 made, otherwise you have full control over the response, aka you may show a 5xx
155 It does _not_ perform internal caching, you should use a reverse proxy cache
156 such as Varnish for this, or those fancy things called CDNs. If your
157 application is small enough that it would benefit from single-node memory
158 caching, it's small enough that it does not need caching at all ;).
162 To enable `debug()` instrumentation output export __DEBUG__:
165 $ DEBUG=send node app
177 ### Serve a specific file
179 This simple example will send a specific file to all requests.
182 var http = require('http')
183 var send = require('send')
185 var server = http.createServer(function onRequest (req, res) {
186 send(req, '/path/to/index.html')
193 ### Serve all files from a directory
195 This simple example will just serve up all the files in a
196 given directory as the top-level. For example, a request
197 `GET /foo.txt` will send back `/www/public/foo.txt`.
200 var http = require('http')
201 var parseUrl = require('parseurl')
202 var send = require('send')
204 var server = http.createServer(function onRequest (req, res) {
205 send(req, parseUrl(req).pathname, { root: '/www/public' })
212 ### Custom file types
215 var http = require('http')
216 var parseUrl = require('parseurl')
217 var send = require('send')
219 // Default unknown types to text/plain
220 send.mime.default_type = 'text/plain'
224 'application/x-my-type': ['x-mt', 'x-mtt']
227 var server = http.createServer(function onRequest (req, res) {
228 send(req, parseUrl(req).pathname, { root: '/www/public' })
235 ### Custom directory index view
237 This is a example of serving up a structure of directories with a
238 custom function to render a listing of a directory.
241 var http = require('http')
242 var fs = require('fs')
243 var parseUrl = require('parseurl')
244 var send = require('send')
246 // Transfer arbitrary files from within /www/example.com/public/*
247 // with a custom handler for directory listing
248 var server = http.createServer(function onRequest (req, res) {
249 send(req, parseUrl(req).pathname, { index: false, root: '/www/public' })
250 .once('directory', directory)
256 // Custom directory handler
257 function directory (res, path) {
260 // redirect to trailing slash for consistent url
261 if (!stream.hasTrailingSlash()) {
262 return stream.redirect(path)
265 // get directory list
266 fs.readdir(path, function onReaddir (err, list) {
267 if (err) return stream.error(err)
269 // render an index for the directory
270 res.setHeader('Content-Type', 'text/plain; charset=UTF-8')
271 res.end(list.join('\n') + '\n')
276 ### Serving from a root directory with custom error-handling
279 var http = require('http')
280 var parseUrl = require('parseurl')
281 var send = require('send')
283 var server = http.createServer(function onRequest (req, res) {
284 // your custom error-handling logic:
285 function error (err) {
286 res.statusCode = err.status || 500
290 // your custom headers
291 function headers (res, path, stat) {
292 // serve all files for download
293 res.setHeader('Content-Disposition', 'attachment')
296 // your custom directory handling logic:
297 function redirect () {
299 res.setHeader('Location', req.url + '/')
300 res.end('Redirecting to ' + req.url + '/')
303 // transfer arbitrary files from within
304 // /www/example.com/public/*
305 send(req, parseUrl(req).pathname, { root: '/www/public' })
307 .on('directory', redirect)
308 .on('headers', headers)
319 [appveyor-image]: https://badgen.net/appveyor/ci/dougwilson/send/master?label=windows
320 [appveyor-url]: https://ci.appveyor.com/project/dougwilson/send
321 [coveralls-image]: https://badgen.net/coveralls/c/github/pillarjs/send/master
322 [coveralls-url]: https://coveralls.io/r/pillarjs/send?branch=master
323 [node-image]: https://badgen.net/npm/node/send
324 [node-url]: https://nodejs.org/en/download/
325 [npm-downloads-image]: https://badgen.net/npm/dm/send
326 [npm-url]: https://npmjs.org/package/send
327 [npm-version-image]: https://badgen.net/npm/v/send
328 [travis-image]: https://badgen.net/travis/pillarjs/send/master?label=linux
329 [travis-url]: https://travis-ci.org/pillarjs/send