You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

329 lines
9.2 KiB

4 years ago
  1. # send
  2. [![NPM Version][npm-version-image]][npm-url]
  3. [![NPM Downloads][npm-downloads-image]][npm-url]
  4. [![Linux Build][travis-image]][travis-url]
  5. [![Windows Build][appveyor-image]][appveyor-url]
  6. [![Test Coverage][coveralls-image]][coveralls-url]
  7. Send is a library for streaming files from the file system as a http response
  8. supporting partial responses (Ranges), conditional-GET negotiation (If-Match,
  9. If-Unmodified-Since, If-None-Match, If-Modified-Since), high test coverage,
  10. and granular events which may be leveraged to take appropriate actions in your
  11. application or framework.
  12. Looking to serve up entire folders mapped to URLs? Try [serve-static](https://www.npmjs.org/package/serve-static).
  13. ## Installation
  14. This is a [Node.js](https://nodejs.org/en/) module available through the
  15. [npm registry](https://www.npmjs.com/). Installation is done using the
  16. [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
  17. ```bash
  18. $ npm install send
  19. ```
  20. ## API
  21. <!-- eslint-disable no-unused-vars -->
  22. ```js
  23. var send = require('send')
  24. ```
  25. ### send(req, path, [options])
  26. Create a new `SendStream` for the given path to send to a `res`. The `req` is
  27. the Node.js HTTP request and the `path` is a urlencoded path to send (urlencoded,
  28. not the actual file-system path).
  29. #### Options
  30. ##### acceptRanges
  31. Enable or disable accepting ranged requests, defaults to true.
  32. Disabling this will not send `Accept-Ranges` and ignore the contents
  33. of the `Range` request header.
  34. ##### cacheControl
  35. Enable or disable setting `Cache-Control` response header, defaults to
  36. true. Disabling this will ignore the `immutable` and `maxAge` options.
  37. ##### dotfiles
  38. Set how "dotfiles" are treated when encountered. A dotfile is a file
  39. or directory that begins with a dot ("."). Note this check is done on
  40. the path itself without checking if the path actually exists on the
  41. disk. If `root` is specified, only the dotfiles above the root are
  42. checked (i.e. the root itself can be within a dotfile when when set
  43. to "deny").
  44. - `'allow'` No special treatment for dotfiles.
  45. - `'deny'` Send a 403 for any request for a dotfile.
  46. - `'ignore'` Pretend like the dotfile does not exist and 404.
  47. The default value is _similar_ to `'ignore'`, with the exception that
  48. this default will not ignore the files within a directory that begins
  49. with a dot, for backward-compatibility.
  50. ##### end
  51. Byte offset at which the stream ends, defaults to the length of the file
  52. minus 1. The end is inclusive in the stream, meaning `end: 3` will include
  53. the 4th byte in the stream.
  54. ##### etag
  55. Enable or disable etag generation, defaults to true.
  56. ##### extensions
  57. If a given file doesn't exist, try appending one of the given extensions,
  58. in the given order. By default, this is disabled (set to `false`). An
  59. example value that will serve extension-less HTML files: `['html', 'htm']`.
  60. This is skipped if the requested file already has an extension.
  61. ##### immutable
  62. Enable or diable the `immutable` directive in the `Cache-Control` response
  63. header, defaults to `false`. If set to `true`, the `maxAge` option should
  64. also be specified to enable caching. The `immutable` directive will prevent
  65. supported clients from making conditional requests during the life of the
  66. `maxAge` option to check if the file has changed.
  67. ##### index
  68. By default send supports "index.html" files, to disable this
  69. set `false` or to supply a new index pass a string or an array
  70. in preferred order.
  71. ##### lastModified
  72. Enable or disable `Last-Modified` header, defaults to true. Uses the file
  73. system's last modified value.
  74. ##### maxAge
  75. Provide a max-age in milliseconds for http caching, defaults to 0.
  76. This can also be a string accepted by the
  77. [ms](https://www.npmjs.org/package/ms#readme) module.
  78. ##### root
  79. Serve files relative to `path`.
  80. ##### start
  81. Byte offset at which the stream starts, defaults to 0. The start is inclusive,
  82. meaning `start: 2` will include the 3rd byte in the stream.
  83. #### Events
  84. The `SendStream` is an event emitter and will emit the following events:
  85. - `error` an error occurred `(err)`
  86. - `directory` a directory was requested `(res, path)`
  87. - `file` a file was requested `(path, stat)`
  88. - `headers` the headers are about to be set on a file `(res, path, stat)`
  89. - `stream` file streaming has started `(stream)`
  90. - `end` streaming has completed
  91. #### .pipe
  92. The `pipe` method is used to pipe the response into the Node.js HTTP response
  93. object, typically `send(req, path, options).pipe(res)`.
  94. ### .mime
  95. The `mime` export is the global instance of of the
  96. [`mime` npm module](https://www.npmjs.com/package/mime).
  97. This is used to configure the MIME types that are associated with file extensions
  98. as well as other options for how to resolve the MIME type of a file (like the
  99. default type to use for an unknown file extension).
  100. ## Error-handling
  101. By default when no `error` listeners are present an automatic response will be
  102. made, otherwise you have full control over the response, aka you may show a 5xx
  103. page etc.
  104. ## Caching
  105. It does _not_ perform internal caching, you should use a reverse proxy cache
  106. such as Varnish for this, or those fancy things called CDNs. If your
  107. application is small enough that it would benefit from single-node memory
  108. caching, it's small enough that it does not need caching at all ;).
  109. ## Debugging
  110. To enable `debug()` instrumentation output export __DEBUG__:
  111. ```
  112. $ DEBUG=send node app
  113. ```
  114. ## Running tests
  115. ```
  116. $ npm install
  117. $ npm test
  118. ```
  119. ## Examples
  120. ### Serve a specific file
  121. This simple example will send a specific file to all requests.
  122. ```js
  123. var http = require('http')
  124. var send = require('send')
  125. var server = http.createServer(function onRequest (req, res) {
  126. send(req, '/path/to/index.html')
  127. .pipe(res)
  128. })
  129. server.listen(3000)
  130. ```
  131. ### Serve all files from a directory
  132. This simple example will just serve up all the files in a
  133. given directory as the top-level. For example, a request
  134. `GET /foo.txt` will send back `/www/public/foo.txt`.
  135. ```js
  136. var http = require('http')
  137. var parseUrl = require('parseurl')
  138. var send = require('send')
  139. var server = http.createServer(function onRequest (req, res) {
  140. send(req, parseUrl(req).pathname, { root: '/www/public' })
  141. .pipe(res)
  142. })
  143. server.listen(3000)
  144. ```
  145. ### Custom file types
  146. ```js
  147. var http = require('http')
  148. var parseUrl = require('parseurl')
  149. var send = require('send')
  150. // Default unknown types to text/plain
  151. send.mime.default_type = 'text/plain'
  152. // Add a custom type
  153. send.mime.define({
  154. 'application/x-my-type': ['x-mt', 'x-mtt']
  155. })
  156. var server = http.createServer(function onRequest (req, res) {
  157. send(req, parseUrl(req).pathname, { root: '/www/public' })
  158. .pipe(res)
  159. })
  160. server.listen(3000)
  161. ```
  162. ### Custom directory index view
  163. This is a example of serving up a structure of directories with a
  164. custom function to render a listing of a directory.
  165. ```js
  166. var http = require('http')
  167. var fs = require('fs')
  168. var parseUrl = require('parseurl')
  169. var send = require('send')
  170. // Transfer arbitrary files from within /www/example.com/public/*
  171. // with a custom handler for directory listing
  172. var server = http.createServer(function onRequest (req, res) {
  173. send(req, parseUrl(req).pathname, { index: false, root: '/www/public' })
  174. .once('directory', directory)
  175. .pipe(res)
  176. })
  177. server.listen(3000)
  178. // Custom directory handler
  179. function directory (res, path) {
  180. var stream = this
  181. // redirect to trailing slash for consistent url
  182. if (!stream.hasTrailingSlash()) {
  183. return stream.redirect(path)
  184. }
  185. // get directory list
  186. fs.readdir(path, function onReaddir (err, list) {
  187. if (err) return stream.error(err)
  188. // render an index for the directory
  189. res.setHeader('Content-Type', 'text/plain; charset=UTF-8')
  190. res.end(list.join('\n') + '\n')
  191. })
  192. }
  193. ```
  194. ### Serving from a root directory with custom error-handling
  195. ```js
  196. var http = require('http')
  197. var parseUrl = require('parseurl')
  198. var send = require('send')
  199. var server = http.createServer(function onRequest (req, res) {
  200. // your custom error-handling logic:
  201. function error (err) {
  202. res.statusCode = err.status || 500
  203. res.end(err.message)
  204. }
  205. // your custom headers
  206. function headers (res, path, stat) {
  207. // serve all files for download
  208. res.setHeader('Content-Disposition', 'attachment')
  209. }
  210. // your custom directory handling logic:
  211. function redirect () {
  212. res.statusCode = 301
  213. res.setHeader('Location', req.url + '/')
  214. res.end('Redirecting to ' + req.url + '/')
  215. }
  216. // transfer arbitrary files from within
  217. // /www/example.com/public/*
  218. send(req, parseUrl(req).pathname, { root: '/www/public' })
  219. .on('error', error)
  220. .on('directory', redirect)
  221. .on('headers', headers)
  222. .pipe(res)
  223. })
  224. server.listen(3000)
  225. ```
  226. ## License
  227. [MIT](LICENSE)
  228. [appveyor-image]: https://badgen.net/appveyor/ci/dougwilson/send/master?label=windows
  229. [appveyor-url]: https://ci.appveyor.com/project/dougwilson/send
  230. [coveralls-image]: https://badgen.net/coveralls/c/github/pillarjs/send/master
  231. [coveralls-url]: https://coveralls.io/r/pillarjs/send?branch=master
  232. [node-image]: https://badgen.net/npm/node/send
  233. [node-url]: https://nodejs.org/en/download/
  234. [npm-downloads-image]: https://badgen.net/npm/dm/send
  235. [npm-url]: https://npmjs.org/package/send
  236. [npm-version-image]: https://badgen.net/npm/v/send
  237. [travis-image]: https://badgen.net/travis/pillarjs/send/master?label=linux
  238. [travis-url]: https://travis-ci.org/pillarjs/send