[Pkg-javascript-commits] [node-serve-static] 01/12: Imported Upstream version 1.6.4

Leo Iannacone l3on-guest at moszumanska.debian.org
Wed Oct 15 15:56:37 UTC 2014


This is an automated email from the git hooks/post-receive script.

l3on-guest pushed a commit to branch master
in repository node-serve-static.

commit 5d7c37af10ede80f8bfc402544b8678550647e81
Author: Leo Iannacone <l3on at ubuntu.com>
Date:   Wed Oct 15 13:30:22 2014 +0200

    Imported Upstream version 1.6.4
---
 .npmignore              |   3 -
 HISTORY.md              | 187 ++++++++++++++++++++++++++++++++++
 History.md              |  66 ------------
 README.md               | 159 +++++++++++++++++++++++++++++
 Readme.md               |  90 -----------------
 index.js                | 146 +++++++++++++--------------
 package.json            |  24 +++--
 test/fixtures/todo.html |   1 +
 test/test.js            | 261 +++++++++++++++++++++++++++++++++++++++++++-----
 9 files changed, 667 insertions(+), 270 deletions(-)

diff --git a/.npmignore b/.npmignore
deleted file mode 100644
index cd39b77..0000000
--- a/.npmignore
+++ /dev/null
@@ -1,3 +0,0 @@
-coverage/
-test/
-.travis.yml
diff --git a/HISTORY.md b/HISTORY.md
new file mode 100644
index 0000000..5435e83
--- /dev/null
+++ b/HISTORY.md
@@ -0,0 +1,187 @@
+1.6.4 / 2014-10-08
+==================
+
+  * Fix redirect loop when index file serving disabled
+
+1.6.3 / 2014-09-24
+==================
+
+  * deps: send at 0.9.3
+    - deps: etag@~1.4.0
+
+1.6.2 / 2014-09-15
+==================
+
+  * deps: send at 0.9.2
+    - deps: depd at 0.4.5
+    - deps: etag@~1.3.1
+    - deps: range-parser@~1.0.2
+
+1.6.1 / 2014-09-07
+==================
+
+  * deps: send at 0.9.1
+    - deps: fresh at 0.2.4
+
+1.6.0 / 2014-09-07
+==================
+
+  * deps: send at 0.9.0
+    - Add `lastModified` option
+    - Use `etag` to generate `ETag` header
+    - deps: debug@~2.0.0
+
+1.5.4 / 2014-09-04
+==================
+
+  * deps: send at 0.8.5
+    - Fix a path traversal issue when using `root`
+    - Fix malicious path detection for empty string path
+
+1.5.3 / 2014-08-17
+==================
+
+  * deps: send at 0.8.3
+
+1.5.2 / 2014-08-14
+==================
+
+  * deps: send at 0.8.2
+    - Work around `fd` leak in Node.js 0.10 for `fs.ReadStream`
+
+1.5.1 / 2014-08-09
+==================
+
+  * Fix parsing of weird `req.originalUrl` values
+  * deps: parseurl@~1.3.0
+  * deps: utils-merge at 1.0.0
+
+1.5.0 / 2014-08-05
+==================
+
+  * deps: send at 0.8.1
+    - Add `extensions` option
+
+1.4.4 / 2014-08-04
+==================
+
+  * deps: send at 0.7.4
+    - Fix serving index files without root dir
+
+1.4.3 / 2014-07-29
+==================
+
+  * deps: send at 0.7.3
+    - Fix incorrect 403 on Windows and Node.js 0.11
+
+1.4.2 / 2014-07-27
+==================
+
+  * deps: send at 0.7.2
+    - deps: depd at 0.4.4
+
+1.4.1 / 2014-07-26
+==================
+
+  * deps: send at 0.7.1
+    - deps: depd at 0.4.3
+
+1.4.0 / 2014-07-21
+==================
+
+  * deps: parseurl@~1.2.0
+    - Cache URLs based on original value
+    - Remove no-longer-needed URL mis-parse work-around
+    - Simplify the "fast-path" `RegExp`
+  * deps: send at 0.7.0
+    - Add `dotfiles` option
+    - deps: debug at 1.0.4
+    - deps: depd at 0.4.2
+
+1.3.2 / 2014-07-11
+==================
+
+  * deps: send at 0.6.0
+    - Cap `maxAge` value to 1 year
+    - deps: debug at 1.0.3
+
+1.3.1 / 2014-07-09
+==================
+
+  * deps: parseurl@~1.1.3
+    - faster parsing of href-only URLs
+
+1.3.0 / 2014-06-28
+==================
+
+  * Add `setHeaders` option
+  * Include HTML link in redirect response
+  * deps: send at 0.5.0
+    - Accept string for `maxAge` (converted by `ms`)
+
+1.2.3 / 2014-06-11
+==================
+
+  * deps: send at 0.4.3
+    - Do not throw un-catchable error on file open race condition
+    - Use `escape-html` for HTML escaping
+    - deps: debug at 1.0.2
+    - deps: finished at 1.2.2
+    - deps: fresh at 0.2.2
+
+1.2.2 / 2014-06-09
+==================
+
+  * deps: send at 0.4.2
+    - fix "event emitter leak" warnings
+    - deps: debug at 1.0.1
+    - deps: finished at 1.2.1
+
+1.2.1 / 2014-06-02
+==================
+
+  * use `escape-html` for escaping
+  * deps: send at 0.4.1
+    - Send `max-age` in `Cache-Control` in correct format
+
+1.2.0 / 2014-05-29
+==================
+
+  * deps: send at 0.4.0
+    - Calculate ETag with md5 for reduced collisions
+    - Fix wrong behavior when index file matches directory
+    - Ignore stream errors after request ends
+    - Skip directories in index file search
+    - deps: debug at 0.8.1
+
+1.1.0 / 2014-04-24
+==================
+
+  * Accept options directly to `send` module
+  * deps: send at 0.3.0
+
+1.0.4 / 2014-04-07
+==================
+
+  * Resolve relative paths at middleware setup
+  * Use parseurl to parse the URL from request
+
+1.0.3 / 2014-03-20
+==================
+
+  * Do not rely on connect-like environments
+
+1.0.2 / 2014-03-06
+==================
+
+  * deps: send at 0.2.0
+
+1.0.1 / 2014-03-05
+==================
+
+  * Add mime export for back-compat
+
+1.0.0 / 2014-03-05
+==================
+
+  * Genesis from `connect`
diff --git a/History.md b/History.md
deleted file mode 100644
index 423a29d..0000000
--- a/History.md
+++ /dev/null
@@ -1,66 +0,0 @@
-1.2.3 / 2014-06-11
-==================
-
-  * deps: send at 0.4.3
-    - Do not throw un-catchable error on file open race condition
-    - Use `escape-html` for HTML escaping
-    - deps: debug at 1.0.2
-    - deps: finished at 1.2.2
-    - deps: fresh at 0.2.2
-
-1.2.2 / 2014-06-09
-==================
-
-  * deps: send at 0.4.2
-    - fix "event emitter leak" warnings
-    - deps: debug at 1.0.1
-    - deps: finished at 1.2.1
-
-1.2.1 / 2014-06-02
-==================
-
-  * use `escape-html` for escaping
-  * deps: send at 0.4.1
-    - Send `max-age` in `Cache-Control` in correct format
-
-1.2.0 / 2014-05-29
-==================
-
-  * deps: send at 0.4.0
-    - Calculate ETag with md5 for reduced collisions
-    - Fix wrong behavior when index file matches directory
-    - Ignore stream errors after request ends
-    - Skip directories in index file search
-    - deps: debug at 0.8.1
-
-1.1.0 / 2014-04-24
-==================
-
-  * Accept options directly to `send` module
-  * deps: send at 0.3.0
-
-1.0.4 / 2014-04-07
-==================
-
-  * Resolve relative paths at middleware setup
-  * Use parseurl to parse the URL from request
-
-1.0.3 / 2014-03-20
-==================
-
-  * Do not rely on connect-like environments
-
-1.0.2 / 2014-03-06
-==================
-
-  * deps: send at 0.2.0
-
-1.0.1 / 2014-03-05
-==================
-
-  * Add mime export for back-compat
-
-1.0.0 / 2014-03-05
-==================
-
-  * Genesis from `connect`
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..96574b3
--- /dev/null
+++ b/README.md
@@ -0,0 +1,159 @@
+# serve-static
+
+[![NPM Version][npm-image]][npm-url]
+[![NPM Downloads][downloads-image]][downloads-url]
+[![Build Status][travis-image]][travis-url]
+[![Test Coverage][coveralls-image]][coveralls-url]
+[![Gratipay][gratipay-image]][gratipay-url]
+
+## Install
+
+```sh
+$ npm install serve-static
+```
+
+## API
+
+```js
+var serveStatic = require('serve-static')
+```
+
+### serveStatic(root, options)
+
+Create a new middleware function to serve files from within a given root
+directory. The file to serve will be determined by combining `req.url`
+with the provided root directory. When a file is not found, instead of
+sending a 404 response, this module will instead call `next()` to move on
+to the next middleware, allowing for stacking and fall-backs.
+
+#### Options
+
+##### dotfiles
+
+ Set how "dotfiles" are treated when encountered. A dotfile is a file
+or directory that begins with a dot ("."). Note this check is done on
+the path itself without checking if the path actually exists on the
+disk. If `root` is specified, only the dotfiles above the root are
+checked (i.e. the root itself can be within a dotfile when when set
+to "deny").
+
+The default value is `'ignore'`.
+
+  - `'allow'` No special treatment for dotfiles.
+  - `'deny'` Send a 403 for any request for a dotfile.
+  - `'ignore'` Pretend like the dotfile does not exist and call `next()`.
+
+##### etag
+
+Enable or disable etag generation, defaults to true.
+
+##### extensions
+
+Set file extension fallbacks. When set, if a file is not found, the given
+extensions will be added to the file name and search for. The first that
+exists will be served. Example: `['html', 'htm']`.
+
+The default value is `false`.
+
+##### index
+
+By default this module will send "index.html" files in response to a request
+on a directory. To disable this set `false` or to supply a new index pass a
+string or an array in preferred order.
+
+##### lastModified
+
+Enable or disable `Last-Modified` header, defaults to true. Uses the file
+system's last modified value.
+
+##### maxAge
+
+Provide a max-age in milliseconds for http caching, defaults to 0. This
+can also be a string accepted by the [ms](https://www.npmjs.org/package/ms#readme)
+module.
+
+##### redirect
+
+Redirect to trailing "/" when the pathname is a dir. Defaults to `true`.
+
+##### setHeaders
+
+Function to set custom headers on response.
+
+## Examples
+
+### Serve files with vanilla node.js http server
+
+```js
+var finalhandler = require('finalhandler')
+var http = require('http')
+var serveStatic = require('serve-static')
+
+// Serve up public/ftp folder
+var serve = serveStatic('public/ftp', {'index': ['index.html', 'index.htm']})
+
+// Create server
+var server = http.createServer(function(req, res){
+  var done = finalhandler(req, res)
+  serve(req, res, done)
+})
+
+// Listen
+server.listen(3000)
+```
+
+### Serve all files as downloads
+
+```js
+var contentDisposition = require('content-disposition')
+var finalhandler = require('finalhandler')
+var http = require('http')
+var serveStatic = require('serve-static')
+
+// Serve up public/ftp folder
+app.use(serveStatic('public/ftp', {
+  'index': false,
+  'setHeaders': setHeaders
+}))
+
+// Set header to force download
+function setHeaders(res, path) {
+  res.setHeader('Content-Disposition', contentDisposition(path))
+}
+
+// Create server
+var server = http.createServer(function(req, res){
+  var done = finalhandler(req, res)
+  serve(req, res, done)
+})
+
+// Listen
+server.listen(3000)
+```
+
+### Serving using express
+
+```js
+var connect = require('connect')
+var serveStatic = require('serve-static')
+
+var app = connect()
+
+app.use(serveStatic('public/ftp', {'index': ['default.html', 'default.htm']}))
+app.listen(3000)
+```
+
+## License
+
+[MIT](LICENSE)
+
+[npm-image]: https://img.shields.io/npm/v/serve-static.svg?style=flat
+[npm-url]: https://npmjs.org/package/serve-static
+[travis-image]: https://img.shields.io/travis/expressjs/serve-static.svg?style=flat
+[travis-url]: https://travis-ci.org/expressjs/serve-static
+[coveralls-image]: https://img.shields.io/coveralls/expressjs/serve-static.svg?style=flat
+[coveralls-url]: https://coveralls.io/r/expressjs/serve-static
+[downloads-image]: https://img.shields.io/npm/dm/serve-static.svg?style=flat
+[downloads-url]: https://npmjs.org/package/serve-static
+[gratipay-image]: https://img.shields.io/gratipay/dougwilson.svg?style=flat
+[gratipay-url]: https://gratipay.com/dougwilson/
diff --git a/Readme.md b/Readme.md
deleted file mode 100644
index 177bebc..0000000
--- a/Readme.md
+++ /dev/null
@@ -1,90 +0,0 @@
-# serve-static
-
-[![NPM version](https://badge.fury.io/js/serve-static.svg)](http://badge.fury.io/js/serve-static)
-[![Build Status](https://travis-ci.org/expressjs/serve-static.svg?branch=master)](https://travis-ci.org/expressjs/serve-static)
-[![Coverage Status](https://img.shields.io/coveralls/expressjs/serve-static.svg?branch=master)](https://coveralls.io/r/expressjs/serve-static)
-
-Previously `connect.static()`.
-
-## Install
-
-```sh
-$ npm install serve-static
-```
-
-## API
-
-```js
-var serveStatic = require('serve-static')
-```
-
-### serveStatic(root, options)
-
-Create a new middleware function to serve files from within a given root
-directory. The file to serve will be determined by combining `req.url`
-with the provided root directory.
-
-Options:
-
-- `hidden` Allow transfer of hidden files. defaults to `false`
-- `index` Default file name, defaults to `'index.html'`
-- `maxAge` Browser cache maxAge in milliseconds. defaults to `0`
-- `redirect` Redirect to trailing "/" when the pathname is a dir. defaults to `true`
-
-## Examples
-
-### Serve files with vanilla node.js http server
-
-```js
-var finalhandler = require('finalhandler')
-var http = require('http')
-var serveStatic = require('serve-static')
-
-// Serve up public/ftp folder
-var serve = serveStatic('public/ftp', {'index': ['index.html', 'index.htm']})
-
-// Create server
-var server = http.createServer(function(req, res){
-  var done = finalhandler(req, res)
-  serve(req, res, done)
-})
-
-// Listen
-server.listen(3000)
-```
-
-### Serve all files from ftp folder
-
-```js
-var connect = require('connect')
-var serveStatic = require('serve-static')
-
-var app = connect()
-
-app.use(serveStatic('public/ftp', {'index': ['default.html', 'default.htm']}))
-app.listen(3000)
-```
-
-## License
-
-The MIT License (MIT)
-
-Copyright (c) 2014 Douglas Christopher Wilson
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/index.js b/index.js
index 1be89c7..12ea659 100644
--- a/index.js
+++ b/index.js
@@ -11,89 +11,102 @@
  */
 
 var escapeHtml = require('escape-html');
+var merge = require('utils-merge');
 var parseurl = require('parseurl');
 var resolve = require('path').resolve;
 var send = require('send');
 var url = require('url');
 
 /**
- * Static:
- *
- *   Static file server with the given `root` path.
- *
- * Examples:
- *
- *     var oneDay = 86400000;
- *     var serveStatic = require('serve-static');
- *
- *     connect()
- *       .use(serveStatic(__dirname + '/public'))
- *
- *     connect()
- *       .use(serveStatic(__dirname + '/public', { maxAge: oneDay }))
- *
- * Options:
- *
- *    - `maxAge`     Browser cache maxAge in milliseconds. defaults to 0
- *    - `hidden`     Allow transfer of hidden files. defaults to false
- *    - `redirect`   Redirect to trailing "/" when the pathname is a dir. defaults to true
- *    - `index`      Default file name, defaults to 'index.html'
- *
- *   Further options are forwarded on to `send`.
- *
  * @param {String} root
  * @param {Object} options
  * @return {Function}
  * @api public
  */
 
-exports = module.exports = function(root, options){
-  options = extend({}, options);
+exports = module.exports = function serveStatic(root, options) {
+  if (!root) {
+    throw new TypeError('root path required')
+  }
+
+  if (typeof root !== 'string') {
+    throw new TypeError('root path must be a string')
+  }
 
-  // root required
-  if (!root) throw new TypeError('root path required');
+  // copy options object
+  options = merge({}, options)
 
   // resolve root to absolute
-  root = resolve(root);
+  root = resolve(root)
 
   // default redirect
-  var redirect = false !== options.redirect;
+  var redirect = options.redirect !== false
+
+  // headers listener
+  var setHeaders = options.setHeaders
+  delete options.setHeaders
+
+  if (setHeaders && typeof setHeaders !== 'function') {
+    throw new TypeError('option setHeaders must be function')
+  }
 
   // setup options for send
-  options.maxage = options.maxage || options.maxAge || 0;
-  options.root = root;
+  options.maxage = options.maxage || options.maxAge || 0
+  options.root = root
 
-  return function staticMiddleware(req, res, next) {
-    if ('GET' != req.method && 'HEAD' != req.method) return next();
-    var opts = extend({}, options);
-    var originalUrl = url.parse(req.originalUrl || req.url);
-    var path = parseurl(req).pathname;
+  return function serveStatic(req, res, next) {
+    if (req.method !== 'GET' && req.method !== 'HEAD') {
+      return next()
+    }
 
-    if (path == '/' && originalUrl.pathname[originalUrl.pathname.length - 1] != '/') {
-      return directory();
+    var opts = merge({}, options)
+    var originalUrl = parseurl.original(req)
+    var path = parseurl(req).pathname
+    var hasTrailingSlash = originalUrl.pathname[originalUrl.pathname.length - 1] === '/'
+
+    if (path === '/' && !hasTrailingSlash) {
+      // make sure redirect occurs at mount
+      path = ''
     }
 
-    function directory() {
-      if (!redirect) return next();
-      var target;
-      originalUrl.pathname += '/';
-      target = url.format(originalUrl);
-      res.statusCode = 303;
-      res.setHeader('Location', target);
-      res.end('Redirecting to ' + escapeHtml(target));
+    // create send stream
+    var stream = send(req, path, opts)
+
+    if (redirect) {
+      // redirect relative to originalUrl
+      stream.on('directory', function redirect() {
+        if (hasTrailingSlash) {
+          return next()
+        }
+
+        originalUrl.pathname += '/'
+
+        var target = url.format(originalUrl)
+
+        res.statusCode = 303
+        res.setHeader('Content-Type', 'text/html; charset=utf-8')
+        res.setHeader('Location', target)
+        res.end('Redirecting to <a href="' + escapeHtml(target) + '">' + escapeHtml(target) + '</a>\n')
+      })
+    } else {
+      // forward to next middleware on directory
+      stream.on('directory', next)
     }
 
-    function error(err) {
-      if (404 == err.status) return next();
-      next(err);
+    // add headers listener
+    if (setHeaders) {
+      stream.on('headers', setHeaders)
     }
 
-    send(req, path, opts)
-      .on('error', error)
-      .on('directory', directory)
-      .pipe(res);
-  };
-};
+    // forward non-404 errors
+    stream.on('error', function error(err) {
+      next(err.status === 404 ? null : err)
+    })
+
+    // pipe
+    stream.pipe(res)
+  }
+}
 
 /**
  * Expose mime module.
@@ -102,23 +115,4 @@ exports = module.exports = function(root, options){
  * reference to the "mime" module in the npm registry.
  */
 
-exports.mime = send.mime;
-
-/**
- * Shallow clone a single object.
- *
- * @param {Object} obj
- * @param {Object} source
- * @return {Object}
- * @api private
- */
-
-function extend(obj, source) {
-  if (!source) return obj;
-
-  for (var prop in source) {
-    obj[prop] = source[prop];
-  }
-
-  return obj;
-};
+exports.mime = send.mime
diff --git a/package.json b/package.json
index 725656a..cc80581 100644
--- a/package.json
+++ b/package.json
@@ -1,27 +1,33 @@
 {
   "name": "serve-static",
   "description": "Serve static files",
-  "version": "1.2.3",
+  "version": "1.6.4",
   "author": "Douglas Christopher Wilson <doug at somethingdoug.com>",
   "license": "MIT",
   "repository": "expressjs/serve-static",
   "dependencies": {
     "escape-html": "1.0.1",
-    "parseurl": "1.0.1",
-    "send": "0.4.3"
+    "parseurl": "~1.3.0",
+    "send": "0.9.3",
+    "utils-merge": "1.0.0"
   },
   "devDependencies": {
-    "istanbul": "0.2.10",
-    "mocha": "~1.20.0",
+    "istanbul": "0.3.2",
+    "mocha": "~1.21.0",
     "should": "~4.0.0",
-    "supertest": "~0.13.0"
+    "supertest": "~0.14.0"
   },
+  "files": [
+    "LICENSE",
+    "HISTORY.md",
+    "index.js"
+  ],
   "engines": {
     "node": ">= 0.8.0"
   },
   "scripts": {
-    "test": "mocha --reporter dot --require should test/",
-    "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --require should test/",
-    "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --require should test/"
+    "test": "mocha --reporter spec --bail --check-leaks --require should test/",
+    "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks --require should test/",
+    "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks --require should test/"
   }
 }
diff --git a/test/fixtures/todo.html b/test/fixtures/todo.html
new file mode 100644
index 0000000..e7af6d7
--- /dev/null
+++ b/test/fixtures/todo.html
@@ -0,0 +1 @@
+<li>groceries</li>
\ No newline at end of file
diff --git a/test/test.js b/test/test.js
index 987cf0e..915a4bd 100644
--- a/test/test.js
+++ b/test/test.js
@@ -16,6 +16,14 @@ describe('serveStatic()', function(){
       server = createServer();
     });
 
+    it('should require root path', function(){
+      serveStatic.bind().should.throw(/root path required/);
+    });
+
+    it('should require root path to be string', function(){
+      serveStatic.bind(null, 42).should.throw(/root path.*string/);
+    });
+
     it('should serve static files', function(done){
       request(server)
       .get('/todo.txt')
@@ -35,6 +43,13 @@ describe('serveStatic()', function(){
       .expect(200, done);
     });
 
+    it('should set Last-Modified', function(done){
+      request(server)
+      .get('/todo.txt')
+      .expect('Last-Modified', /\d{2} \w{3} \d{4}/)
+      .expect(200, done)
+    })
+
     it('should default max-age=0', function(done){
       request(server)
       .get('/todo.txt')
@@ -54,24 +69,6 @@ describe('serveStatic()', function(){
       .expect(404, done);
     });
 
-    it('should redirect directories with query string', function (done) {
-      request(server)
-      .get('/users?name=john')
-      .expect('Location', '/users/?name=john', done);
-    });
-
-    it('should redirect directories', function(done){
-      request(server)
-      .get('/users')
-      .expect(303, done);
-    });
-
-    it('should not redirect incorrectly', function (done) {
-      request(server)
-      .get('/')
-      .expect(404, done);
-    });
-
     it('should support index.html', function(done){
       request(server)
       .get('/users/')
@@ -92,6 +89,12 @@ describe('serveStatic()', function(){
       .expect(200, '', done);
     });
 
+    it('should skip POST requests', function(done){
+      request(server)
+      .post('/todo.txt')
+      .expect(404, 'sorry!', done);
+    });
+
     it('should support conditional requests', function(done){
       request(server)
       .get('/todo.txt')
@@ -132,33 +135,195 @@ describe('serveStatic()', function(){
     })
   })
 
+  describe('extensions', function () {
+    it('should be not be enabled by default', function (done) {
+      var server = createServer(fixtures);
+
+      request(server)
+      .get('/todo')
+      .expect(404, done);
+    })
+
+    it('should be configurable', function (done) {
+      var server = createServer(fixtures, {'extensions': 'txt'});
+
+      request(server)
+      .get('/todo')
+      .expect(200, '- groceries', done);
+    })
+
+    it('should support disabling extensions', function (done) {
+      var server = createServer(fixtures, {'extensions': false});
+
+      request(server)
+      .get('/todo')
+      .expect(404, done);
+    })
+
+    it('should support fallbacks', function (done) {
+      var server = createServer(fixtures, {'extensions': ['htm', 'html', 'txt']});
+
+      request(server)
+      .get('/todo')
+      .expect(200, '<li>groceries</li>', done);
+    })
+
+    it('should 404 if nothing found', function (done) {
+      var server = createServer(fixtures, {'extensions': ['htm', 'html', 'txt']});
+
+      request(server)
+      .get('/bob')
+      .expect(404, done)
+    })
+  })
+
   describe('hidden files', function(){
     var server;
     before(function () {
-      server = createServer(fixtures, {'hidden': true});
+      server = createServer(fixtures, {'dotfiles': 'allow'});
     });
 
-    it('should be served when hidden: true is given', function(done){
+    it('should be served when dotfiles: "allow" is given', function(done){
       request(server)
       .get('/.hidden')
       .expect(200, 'I am hidden', done);
     })
   })
 
+  describe('lastModified', function(){
+    describe('when false', function () {
+      it('should not include Last-Modifed', function (done) {
+        request(createServer(fixtures, {'lastModified': false}))
+        .get('/nums')
+        .expect(200, '123456789', function (err, res) {
+          if (err) return done(err)
+          res.headers.should.not.have.property('last-modified')
+          done()
+        })
+      })
+    })
+
+    describe('when true', function () {
+      it('should include Last-Modifed', function (done) {
+        request(createServer(fixtures, {'lastModified': true}))
+        .get('/nums')
+        .expect(200, '123456789', function (err, res) {
+          if (err) return done(err)
+          res.headers.should.have.property('last-modified')
+          done()
+        })
+      })
+    })
+  })
+
   describe('maxAge', function(){
-    var server;
-    before(function () {
-      server = createServer(fixtures, {'maxAge': Infinity});
-    });
+    it('should accept string', function(done){
+      request(createServer(fixtures, {'maxAge': '30d'}))
+      .get('/todo.txt')
+      .expect('cache-control', 'public, max-age=' + 60*60*24*30)
+      .expect(200, done)
+    })
 
     it('should be reasonable when infinite', function(done){
-      request(server)
+      request(createServer(fixtures, {'maxAge': Infinity}))
       .get('/todo.txt')
       .expect('cache-control', 'public, max-age=' + 60*60*24*365)
       .expect(200, done)
     });
   });
 
+  describe('redirect', function () {
+    var server;
+    before(function () {
+      server = createServer(fixtures)
+    })
+
+    it('should redirect directories', function(done){
+      request(server)
+      .get('/users')
+      .expect('Location', '/users/')
+      .expect(303, done)
+    })
+
+    it('should include HTML link', function(done){
+      request(server)
+      .get('/users')
+      .expect('Location', '/users/')
+      .expect(303, /<a href="\/users\/">/, done)
+    })
+
+    it('should redirect directories with query string', function (done) {
+      request(server)
+      .get('/users?name=john')
+      .expect('Location', '/users/?name=john')
+      .expect(303, done)
+    })
+
+    it('should not redirect incorrectly', function (done) {
+      request(server)
+      .get('/')
+      .expect(404, done)
+    })
+
+    describe('when false', function () {
+      var server;
+      before(function () {
+        server = createServer(fixtures, {'redirect': false})
+      })
+
+      it('should disable redirect', function (done) {
+        request(server)
+        .get('/users')
+        .expect(404, done)
+      })
+    })
+  })
+
+  describe('setHeaders', function () {
+    it('should reject non-functions', function () {
+      serveStatic.bind(null, fixtures, {'setHeaders': 3}).should.throw(/setHeaders.*function/)
+    })
+
+    it('should get called when sending file', function(done){
+      var server = createServer(fixtures, {'setHeaders': function (res) {
+        res.setHeader('x-custom', 'set')
+      }})
+
+      request(server)
+      .get('/nums')
+      .expect('x-custom', 'set')
+      .expect(200, done)
+    })
+
+    it('should not get called on 404', function(done){
+      var server = createServer(fixtures, {'setHeaders': function (res) {
+        res.setHeader('x-custom', 'set')
+      }})
+
+      request(server)
+      .get('/bogus')
+      .expect(404, function (err, res) {
+        if (err) return done(err)
+        res.headers.should.not.have.property('x-custom')
+        done()
+      })
+    })
+
+    it('should not get called on redirect', function(done){
+      var server = createServer(fixtures, {'setHeaders': function (res) {
+        res.setHeader('x-custom', 'set')
+      }})
+
+      request(server)
+      .get('/users')
+      .expect(303, function (err, res) {
+        if (err) return done(err)
+        res.headers.should.not.have.property('x-custom')
+        done()
+      })
+    })
+  })
+
   describe('when traversing passed root', function(){
     var server;
     before(function () {
@@ -353,7 +518,7 @@ describe('serveStatic()', function(){
     before(function () {
       server = createServer(fixtures, null, function (req) {
         req.originalUrl = req.url;
-        req.url = '/' + req.url.split('/').slice(2).join('/');
+        req.url = '/' + req.url.split('/').slice(3).join('/');
       });
     });
 
@@ -363,6 +528,13 @@ describe('serveStatic()', function(){
       .expect('Location', '/static/users/')
       .expect(303, done);
     });
+
+    it('should not choke on auth-looking URL', function(done){
+      request(server)
+      .get('//todo at txt')
+      .expect('Location', '//todo at txt/')
+      .expect(303, done);
+    });
   });
 
   describe('when responding non-2xx or 304', function(){
@@ -387,6 +559,43 @@ describe('serveStatic()', function(){
       });
     });
   });
+
+  describe('when index file serving disabled', function(){
+    var server;
+    before(function () {
+      server = createServer(fixtures, {'index': false}, function (req) {
+        // mimic express/connect mount
+        req.originalUrl = req.url;
+        req.url = '/' + req.url.split('/').slice(2).join('/');
+      });
+    });
+
+    it('should next() on directory', function (done) {
+      request(server)
+      .get('/static/users/')
+      .expect(404, 'sorry!', done);
+    });
+
+    it('should redirect to trailing slash', function (done) {
+      request(server)
+      .get('/static/users')
+      .expect('Location', '/static/users/')
+      .expect(303, done);
+    });
+
+    it('should next() on mount point', function (done) {
+      request(server)
+      .get('/static/')
+      .expect(404, 'sorry!', done);
+    });
+
+    it('should redirect to trailing slash mount point', function (done) {
+      request(server)
+      .get('/static')
+      .expect('Location', '/static/')
+      .expect(303, done);
+    });
+  });
 });
 
 function createServer(dir, opts, fn) {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-serve-static.git



More information about the Pkg-javascript-commits mailing list