1 | # send
|
2 |
|
3 | [![NPM version](https://badge.fury.io/js/send.svg)](https://badge.fury.io/js/send)
|
4 | [![Build Status](https://travis-ci.org/visionmedia/send.svg?branch=master)](https://travis-ci.org/visionmedia/send)
|
5 | [![Coverage Status](https://img.shields.io/coveralls/visionmedia/send.svg?branch=master)](https://coveralls.io/r/visionmedia/send)
|
6 |
|
7 | Send is Connect's `static()` extracted for generalized use, a streaming static file
|
8 | server supporting partial responses (Ranges), conditional-GET negotiation, high test coverage, and granular events which may be leveraged to take appropriate actions in your application or framework.
|
9 |
|
10 | ## Installation
|
11 |
|
12 | $ npm install send
|
13 |
|
14 | ## Examples
|
15 |
|
16 | Small:
|
17 |
|
18 | ```js
|
19 | var http = require('http');
|
20 | var send = require('send');
|
21 |
|
22 | var app = http.createServer(function(req, res){
|
23 | send(req, req.url).pipe(res);
|
24 | }).listen(3000);
|
25 | ```
|
26 |
|
27 | Serving from a root directory with custom error-handling:
|
28 |
|
29 | ```js
|
30 | var http = require('http');
|
31 | var send = require('send');
|
32 | var url = require('url');
|
33 |
|
34 | var app = http.createServer(function(req, res){
|
35 | // your custom error-handling logic:
|
36 | function error(err) {
|
37 | res.statusCode = err.status || 500;
|
38 | res.end(err.message);
|
39 | }
|
40 |
|
41 | // your custom headers
|
42 | function headers(res, path, stat) {
|
43 | // serve all files for download
|
44 | res.setHeader('Content-Disposition', 'attachment');
|
45 | }
|
46 |
|
47 | // your custom directory handling logic:
|
48 | function redirect() {
|
49 | res.statusCode = 301;
|
50 | res.setHeader('Location', req.url + '/');
|
51 | res.end('Redirecting to ' + req.url + '/');
|
52 | }
|
53 |
|
54 | // transfer arbitrary files from within
|
55 | // /www/example.com/public/*
|
56 | send(req, url.parse(req.url).pathname, {root: '/www/example.com/public'})
|
57 | .on('error', error)
|
58 | .on('directory', redirect)
|
59 | .on('headers', headers)
|
60 | .pipe(res);
|
61 | }).listen(3000);
|
62 | ```
|
63 |
|
64 | ## API
|
65 |
|
66 | ### Options
|
67 |
|
68 | #### etag
|
69 |
|
70 | Enable or disable etag generation, defaults to true.
|
71 |
|
72 | #### hidden
|
73 |
|
74 | Enable or disable transfer of hidden files, defaults to false.
|
75 |
|
76 | #### index
|
77 |
|
78 | By default send supports "index.html" files, to disable this
|
79 | set `false` or to supply a new index pass a string or an array
|
80 | in preferred order.
|
81 |
|
82 | #### maxAge
|
83 |
|
84 | Provide a max-age in milliseconds for http caching, defaults to 0.
|
85 | This can also be a string accepted by the
|
86 | [ms](https://www.npmjs.org/package/ms#readme) module.
|
87 |
|
88 | #### root
|
89 |
|
90 | Serve files relative to `path`.
|
91 |
|
92 | ### Events
|
93 |
|
94 | - `error` an error occurred `(err)`
|
95 | - `directory` a directory was requested
|
96 | - `file` a file was requested `(path, stat)`
|
97 | - `headers` the headers are about to be set on a file `(res, path, stat)`
|
98 | - `stream` file streaming has started `(stream)`
|
99 | - `end` streaming has completed
|
100 |
|
101 | ## Error-handling
|
102 |
|
103 | By default when no `error` listeners are present an automatic response will be made, otherwise you have full control over the response, aka you may show a 5xx page etc.
|
104 |
|
105 | ## Caching
|
106 |
|
107 | It does _not_ perform internal caching, you should use a reverse proxy cache such
|
108 | as Varnish for this, or those fancy things called CDNs. If your application is small enough that it would benefit from single-node memory caching, it's small enough that it does not need caching at all ;).
|
109 |
|
110 | ## Debugging
|
111 |
|
112 | To enable `debug()` instrumentation output export __DEBUG__:
|
113 |
|
114 | ```
|
115 | $ DEBUG=send node app
|
116 | ```
|
117 |
|
118 | ## Running tests
|
119 |
|
120 | ```
|
121 | $ npm install
|
122 | $ npm test
|
123 | ```
|
124 |
|
125 | ## License
|
126 |
|
127 | (The MIT License)
|
128 |
|
129 | Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>
|
130 |
|
131 | Permission is hereby granted, free of charge, to any person obtaining
|
132 | a copy of this software and associated documentation files (the
|
133 | 'Software'), to deal in the Software without restriction, including
|
134 | without limitation the rights to use, copy, modify, merge, publish,
|
135 | distribute, sublicense, and/or sell copies of the Software, and to
|
136 | permit persons to whom the Software is furnished to do so, subject to
|
137 | the following conditions:
|
138 |
|
139 | The above copyright notice and this permission notice shall be
|
140 | included in all copies or substantial portions of the Software.
|
141 |
|
142 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
143 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
144 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
145 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
146 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
147 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
148 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|