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.

327 lines
9.3 KiB

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