[Pkg-javascript-commits] [node-serve-static] 01/02: Imported Upstream version 1.1.0

Leo Iannacone l3on-guest at moszumanska.debian.org
Mon Apr 28 10:34:32 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 3198d240d88e732899d18230d8d84c15e2d7078c
Author: Leo Iannacone <l3on at ubuntu.com>
Date:   Mon Apr 28 12:11:51 2014 +0200

    Imported Upstream version 1.1.0
---
 .gitignore                     |  65 ++++++
 .npmignore                     |   1 +
 .travis.yml                    |   5 +
 History.md                     |  31 +++
 LICENSE                        |  25 +++
 Readme.md                      |  41 ++++
 index.js                       | 139 ++++++++++++
 package.json                   |  30 +++
 test/fixtures/.hidden          |   1 +
 test/fixtures/foo bar          |   1 +
 test/fixtures/nums             |   1 +
 test/fixtures/todo.txt         |   1 +
 test/fixtures/users/index.html |   1 +
 test/fixtures/users/tobi.txt   |   1 +
 test/test.js                   | 473 +++++++++++++++++++++++++++++++++++++++++
 15 files changed, 816 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c4cdf95
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,65 @@
+# Compiled source #
+###################
+*.com
+*.class
+*.dll
+*.exe
+*.o
+*.so
+
+# Packages #
+############
+# it's better to unpack these files and commit the raw source
+# git has its own built in compression methods
+*.7z
+*.dmg
+*.gz
+*.iso
+*.jar
+*.rar
+*.tar
+*.zip
+
+# Logs and databases #
+######################
+*.log
+*.sql
+*.sqlite
+
+# OS generated files #
+######################
+.DS_Store*
+ehthumbs.db
+Thumbs.db
+
+# Node.js #
+###########
+lib-cov
+*.seed
+*.log
+*.csv
+*.dat
+*.out
+*.pid
+*.gz
+
+pids
+logs
+results
+
+node_modules
+npm-debug.log
+
+# Git #
+#######
+*.orig
+*.BASE.*
+*.BACKUP.*
+*.LOCAL.*
+*.REMOTE.*
+
+# Components #
+##############
+
+/build
+/components
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..9daeafb
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1 @@
+test
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..99cdc74
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,5 @@
+language: node_js
+node_js:
+  - "0.8"
+  - "0.10"
+  - "0.11"
diff --git a/History.md b/History.md
new file mode 100644
index 0000000..442e1d3
--- /dev/null
+++ b/History.md
@@ -0,0 +1,31 @@
+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/LICENSE b/LICENSE
new file mode 100644
index 0000000..b7bc085
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,25 @@
+(The MIT License)
+
+Copyright (c) 2010 Sencha Inc.
+Copyright (c) 2011 LearnBoost
+Copyright (c) 2011 TJ Holowaychuk
+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/Readme.md b/Readme.md
new file mode 100644
index 0000000..af1caaa
--- /dev/null
+++ b/Readme.md
@@ -0,0 +1,41 @@
+# Serve Static
+
+Previously `connect.static()`.
+
+[![Build Status](https://travis-ci.org/expressjs/serve-static.svg?branch=master)](https://travis-ci.org/expressjs/serve-static)
+
+Usage:
+
+```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();
+```
+
+## 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
new file mode 100644
index 0000000..d0043fb
--- /dev/null
+++ b/index.js
@@ -0,0 +1,139 @@
+/*!
+ * Connect - static
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * Copyright(c) 2014 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+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);
+
+  // root required
+  if (!root) throw new TypeError('root path required');
+
+  // resolve root to absolute
+  root = resolve(root);
+
+  // default redirect
+  var redirect = false !== options.redirect;
+
+  // setup options for send
+  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;
+
+    if (path == '/' && originalUrl.pathname[originalUrl.pathname.length - 1] != '/') {
+      return directory();
+    }
+
+    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 ' + escape(target));
+    }
+
+    function error(err) {
+      if (404 == err.status) return next();
+      next(err);
+    }
+
+    send(req, path, opts)
+      .on('error', error)
+      .on('directory', directory)
+      .pipe(res);
+  };
+};
+
+/**
+ * Expose mime module.
+ *
+ * If you wish to extend the mime table use this
+ * reference to the "mime" module in the npm registry.
+ */
+
+exports.mime = send.mime;
+
+/**
+ * Escape the given string of `html`.
+ *
+ * @param {String} html
+ * @return {String}
+ * @api private
+ */
+
+function escape(html) {
+  return String(html)
+    .replace(/&(?!\w+;)/g, '&')
+    .replace(/</g, '<')
+    .replace(/>/g, '>')
+    .replace(/"/g, '"');
+};
+
+/**
+ * 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;
+};
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..1636a66
--- /dev/null
+++ b/package.json
@@ -0,0 +1,30 @@
+{
+  "name": "serve-static",
+  "description": "Serve static files",
+  "version": "1.1.0",
+  "author": "Douglas Christopher Wilson <doug at somethingdoug.com>",
+  "license": "MIT",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/expressjs/serve-static.git"
+  },
+  "bugs": {
+    "url": "https://github.com/expressjs/serve-static/issues"
+  },
+  "dependencies": {
+    "parseurl": "1.0.1",
+    "send": "0.3.0"
+  },
+  "devDependencies": {
+    "connect": "~2.14.1",
+    "mocha": "~1.18.2",
+    "should": "~3.3.0",
+    "supertest": "~0.11.0"
+  },
+  "engines": {
+    "node": ">= 0.8.0"
+  },
+  "scripts": {
+    "test": "mocha --reporter spec --require should"
+  }
+}
diff --git a/test/fixtures/.hidden b/test/fixtures/.hidden
new file mode 100644
index 0000000..b885243
--- /dev/null
+++ b/test/fixtures/.hidden
@@ -0,0 +1 @@
+I am hidden
\ No newline at end of file
diff --git a/test/fixtures/foo bar b/test/fixtures/foo bar
new file mode 100644
index 0000000..3f95386
--- /dev/null
+++ b/test/fixtures/foo bar	
@@ -0,0 +1 @@
+baz
\ No newline at end of file
diff --git a/test/fixtures/nums b/test/fixtures/nums
new file mode 100644
index 0000000..e2e107a
--- /dev/null
+++ b/test/fixtures/nums
@@ -0,0 +1 @@
+123456789
\ No newline at end of file
diff --git a/test/fixtures/todo.txt b/test/fixtures/todo.txt
new file mode 100644
index 0000000..8c3539d
--- /dev/null
+++ b/test/fixtures/todo.txt
@@ -0,0 +1 @@
+- groceries
\ No newline at end of file
diff --git a/test/fixtures/users/index.html b/test/fixtures/users/index.html
new file mode 100644
index 0000000..00a2db4
--- /dev/null
+++ b/test/fixtures/users/index.html
@@ -0,0 +1 @@
+<p>tobi, loki, jane</p>
\ No newline at end of file
diff --git a/test/fixtures/users/tobi.txt b/test/fixtures/users/tobi.txt
new file mode 100644
index 0000000..9d9529d
--- /dev/null
+++ b/test/fixtures/users/tobi.txt
@@ -0,0 +1 @@
+ferret
\ No newline at end of file
diff --git a/test/test.js b/test/test.js
new file mode 100644
index 0000000..d1a37f5
--- /dev/null
+++ b/test/test.js
@@ -0,0 +1,473 @@
+
+process.env.NODE_ENV = 'test';
+
+var connect = require('connect');
+var http = require('http');
+var path = require('path');
+var request = require('supertest');
+var serveStatic = require('..');
+
+var fixtures = __dirname + '/fixtures';
+var relative = path.relative(process.cwd(), fixtures);
+
+var skipRelative = ~relative.indexOf('..') || path.resolve(relative) === relative;
+
+describe('serveStatic()', function(){
+  describe('basic operations', function(){
+    var server;
+    before(function () {
+      server = createServer();
+    });
+    after(function (done) {
+      server.close(done);
+    });
+
+    it('should serve static files', function(done){
+      request(server)
+      .get('/todo.txt')
+      .expect(200, '- groceries', done);
+    });
+
+    it('should support nesting', function(done){
+      request(server)
+      .get('/users/tobi.txt')
+      .expect(200, 'ferret', done);
+    });
+
+    it('should set Content-Type', function(done){
+      request(server)
+      .get('/todo.txt')
+      .expect('Content-Type', 'text/plain; charset=UTF-8')
+      .expect(200, done);
+    });
+
+    it('should default max-age=0', function(done){
+      request(server)
+      .get('/todo.txt')
+      .expect('Cache-Control', 'public, max-age=0')
+      .expect(200, done);
+    });
+
+    it('should support urlencoded pathnames', function(done){
+      request(server)
+      .get('/foo%20bar')
+      .expect(200, 'baz', done);
+    });
+
+    it('should not choke on auth-looking URL', function(done){
+      request(server)
+      .get('//todo at txt')
+      .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/')
+      .expect(200)
+      .expect('Content-Type', /html/)
+      .expect('<p>tobi, loki, jane</p>', done);
+    });
+
+    it('should support ../', function(done){
+      request(server)
+      .get('/users/../todo.txt')
+      .expect(200, '- groceries', done);
+    });
+
+    it('should support HEAD', function(done){
+      request(server)
+      .head('/todo.txt')
+      .expect(200, '', done);
+    });
+
+    it('should support conditional requests', function(done){
+      request(server)
+      .get('/todo.txt')
+      .end(function(err, res){
+        if (err) throw err;
+        request(server)
+        .get('/todo.txt')
+        .set('If-None-Match', res.headers.etag)
+        .expect(304, done);
+      });
+    });
+
+    it('should ignore hidden files', function(done){
+      request(server)
+      .get('/.hidden')
+      .expect(404, done);
+    });
+
+    it('should set max-age=0 by default', function(done){
+      request(server)
+      .get('/todo.txt')
+      .expect('cache-control', 'public, max-age=0')
+      .expect(200, done)
+    });
+  });
+
+  (skipRelative ? describe.skip : describe)('current dir', function(){
+    var server;
+    before(function () {
+      server = createServer('.');
+    });
+    after(function (done) {
+      server.close(done);
+    });
+
+    it('should be served with "."', function(done){
+      var dest = relative.split(path.sep).join('/');
+      request(server)
+      .get('/' + dest + '/todo.txt')
+      .expect(200, '- groceries', done);
+    })
+  })
+
+  describe('hidden files', function(){
+    var server;
+    before(function () {
+      server = createServer(fixtures, {'hidden': true});
+    });
+    after(function (done) {
+      server.close(done);
+    });
+
+    it('should be served when hidden: true is given', function(done){
+      request(server)
+      .get('/.hidden')
+      .expect(200, 'I am hidden', done);
+    })
+  })
+
+  describe('maxAge', function(){
+    var server;
+    before(function () {
+      server = createServer(fixtures, {'maxAge': Infinity});
+    });
+    after(function (done) {
+      server.close(done);
+    });
+
+    it('should be reasonable when infinite', function(done){
+      request(server)
+      .get('/todo.txt')
+      .expect('cache-control', 'public, max-age=' + 60*60*24*365)
+      .expect(200, done)
+    });
+  });
+
+  describe('when traversing passed root', function(){
+    var server;
+    before(function () {
+      server = createServer();
+    });
+    after(function (done) {
+      server.close(done);
+    });
+
+    it('should respond with 403 Forbidden', function(done){
+      request(server)
+      .get('/users/../../todo.txt')
+      .expect(403, done);
+    })
+
+    it('should catch urlencoded ../', function(done){
+      request(server)
+      .get('/users/%2e%2e/%2e%2e/todo.txt')
+      .expect(403, done);
+    });
+  });
+
+  describe('on ENOENT', function(){
+    var server;
+    before(function () {
+      server = createServer();
+    });
+    after(function (done) {
+      server.close(done);
+    });
+
+    it('should next()', function(done){
+      request(server)
+      .get('/does-not-exist')
+      .expect(404, 'sorry!', done);
+    });
+  });
+
+  describe('Range', function(){
+    var server;
+    before(function () {
+      server = createServer();
+    });
+    after(function (done) {
+      server.close(done);
+    });
+
+    it('should support byte ranges', function(done){
+      request(server)
+      .get('/nums')
+      .set('Range', 'bytes=0-4')
+      .expect('12345', done);
+    });
+
+    it('should be inclusive', function(done){
+      request(server)
+      .get('/nums')
+      .set('Range', 'bytes=0-0')
+      .expect('1', done);
+    });
+
+    it('should set Content-Range', function(done){
+      request(server)
+      .get('/nums')
+      .set('Range', 'bytes=2-5')
+      .expect('Content-Range', 'bytes 2-5/9', done);
+    });
+
+    it('should support -n', function(done){
+      request(server)
+      .get('/nums')
+      .set('Range', 'bytes=-3')
+      .expect('789', done);
+    });
+
+    it('should support n-', function(done){
+      request(server)
+      .get('/nums')
+      .set('Range', 'bytes=3-')
+      .expect('456789', done);
+    });
+
+    it('should respond with 206 "Partial Content"', function(done){
+      request(server)
+      .get('/nums')
+      .set('Range', 'bytes=0-4')
+      .expect(206, done);
+    });
+
+    it('should set Content-Length to the # of octets transferred', function(done){
+      request(server)
+      .get('/nums')
+      .set('Range', 'bytes=2-3')
+      .expect('Content-Length', '2')
+      .expect(206, '34', done);
+    });
+
+    describe('when last-byte-pos of the range is greater than current length', function(){
+      it('is taken to be equal to one less than the current length', function(done){
+        request(server)
+        .get('/nums')
+        .set('Range', 'bytes=2-50')
+        .expect('Content-Range', 'bytes 2-8/9', done)
+      });
+
+      it('should adapt the Content-Length accordingly', function(done){
+        request(server)
+        .get('/nums')
+        .set('Range', 'bytes=2-50')
+        .expect('Content-Length', '7')
+        .expect(206, done);
+      });
+    });
+
+    describe('when the first- byte-pos of the range is greater than the current length', function(){
+      it('should respond with 416', function(done){
+        request(server)
+        .get('/nums')
+        .set('Range', 'bytes=9-50')
+        .expect(416, done);
+      });
+
+      it('should include a Content-Range field with a byte-range- resp-spec of "*" and an instance-length specifying the current length', function(done){
+        request(server)
+        .get('/nums')
+        .set('Range', 'bytes=9-50')
+        .expect('Content-Range', 'bytes */9', done)
+      });
+    });
+
+    describe('when syntactically invalid', function(){
+      it('should respond with 200 and the entire contents', function(done){
+        request(server)
+        .get('/nums')
+        .set('Range', 'asdf')
+        .expect('123456789', done);
+      });
+    });
+  });
+
+  describe('with a malformed URL', function(){
+    var server;
+    before(function () {
+      server = createServer();
+    });
+    after(function (done) {
+      server.close(done);
+    });
+
+    it('should respond with 400', function(done){
+      request(server)
+      .get('/%')
+      .expect(400, done);
+    });
+  });
+
+  describe('on ENAMETOOLONG', function(){
+    var server;
+    before(function () {
+      server = createServer();
+    });
+    after(function (done) {
+      server.close(done);
+    });
+
+    it('should next()', function(done){
+      var path = Array(100).join('foobar');
+
+      request(server)
+      .get('/' + path)
+      .expect(404, done);
+    });
+  });
+
+  describe('on ENOTDIR', function(){
+    var server;
+    before(function () {
+      server = createServer();
+    });
+    after(function (done) {
+      server.close(done);
+    });
+
+    it('should next()', function(done) {
+      request(server)
+      .get('/todo.txt/a.php')
+      .expect(404, done);
+    });
+  });
+
+  describe('when index at mount point', function(){
+    var server;
+    before(function () {
+      var app = connect();
+      app.use('/users', serveStatic('test/fixtures/users'));
+      server = app.listen();
+    });
+    after(function (done) {
+      server.close(done);
+    });
+
+    it('should redirect correctly', function (done) {
+      request(server)
+      .get('/users')
+      .expect('Location', '/users/')
+      .expect(303, done);
+    });
+  });
+
+  describe('when mounted', function(){
+    var server;
+    before(function () {
+      var app = connect();
+      app.use('/static', serveStatic(fixtures));
+      server = app.listen();
+    });
+    after(function (done) {
+      server.close(done);
+    });
+
+    it('should redirect relative to the originalUrl', function(done){
+      request(server)
+      .get('/static/users')
+      .expect('Location', '/static/users/')
+      .expect(303, done);
+    });
+  });
+
+  describe('when responding non-2xx or 304', function(){
+    var server;
+    before(function () {
+      var app = connect();
+      var n = 0;
+
+      app.use(function(req, res, next){
+        switch (n++) {
+          case 0: return next();
+          case 1: res.statusCode = 500; return next();
+        }
+      });
+
+      app.use(serveStatic(fixtures));
+
+      server = app.listen();
+    });
+    after(function (done) {
+      server.close(done);
+    });
+
+    it('should respond as-is', function(done){
+      request(server)
+      .get('/todo.txt')
+      .expect(200)
+      .end(function(err, res){
+        if (err) throw err;
+        request(server)
+        .get('/todo.txt')
+        .set('If-None-Match', res.headers.etag)
+        .expect(500, '- groceries', done);
+      });
+    });
+  });
+
+  describe('raw http server', function(){
+    var server;
+    before(function () {
+      var middleware = serveStatic(fixtures);
+      server = http.createServer(function (req, res) {
+        middleware(req, res, function (err) {
+          res.statusCode = err ? 500 : 404;
+          res.end(err ? err.stack : '');
+        });
+      });
+      server.listen();
+    });
+    after(function (done) {
+      server.close(done);
+    });
+
+    it('should work on raw node.js http servers', function(done){
+      request(server)
+      .get('/todo.txt')
+      .expect(200, '- groceries', done);
+    });
+  });
+});
+
+function createServer(dir, opts) {
+  var app = connect();
+  dir = dir || fixtures;
+  app.use(serveStatic(dir, opts));
+  app.use(function(req, res){
+    res.statusCode = 404;
+    res.end('sorry!');
+  });
+  return app.listen();
+}

-- 
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