Commit b62e3775 authored by Leo Iannacone's avatar Leo Iannacone

update libraries

parent 0f5e5af7
1.0.7 / 2014-07-04
==================
* Fix wrong type returned from `type` when match after unknown extension
1.0.6 / 2014-06-24 1.0.6 / 2014-06-24
================== ==================
......
...@@ -60,8 +60,8 @@ Accepts.prototype.types = function (types) { ...@@ -60,8 +60,8 @@ Accepts.prototype.types = function (types) {
var n = this.negotiator; var n = this.negotiator;
if (!types.length) return n.mediaTypes(); if (!types.length) return n.mediaTypes();
if (!this.headers.accept) return types[0]; if (!this.headers.accept) return types[0];
var mimes = types.map(extToMime).filter(validMime); var mimes = types.map(extToMime);
var accepts = n.mediaTypes(mimes); var accepts = n.mediaTypes(mimes.filter(validMime));
var first = accepts[0]; var first = accepts[0];
if (!first) return false; if (!first) return false;
return types[mimes.indexOf(first)]; return types[mimes.indexOf(first)];
......
...@@ -45,9 +45,5 @@ ...@@ -45,9 +45,5 @@
}, },
"dependencies": {}, "dependencies": {},
"_id": "negotiator@0.4.7", "_id": "negotiator@0.4.7",
"dist": { "_from": "negotiator@0.4.7"
"shasum": "8273ad98ad1c14fed21daa9a404fb6a102d47305"
},
"_from": "negotiator@0.4.7",
"_resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.7.tgz"
} }
{ {
"name": "accepts", "name": "accepts",
"description": "Higher-level content negotiation", "description": "Higher-level content negotiation",
"version": "1.0.6", "version": "1.0.7",
"author": { "author": {
"name": "Jonathan Ong", "name": "Jonathan Ong",
"email": "me@jongleberry.com", "email": "me@jongleberry.com",
...@@ -34,10 +34,10 @@ ...@@ -34,10 +34,10 @@
"bugs": { "bugs": {
"url": "https://github.com/expressjs/accepts/issues" "url": "https://github.com/expressjs/accepts/issues"
}, },
"_id": "accepts@1.0.6", "_id": "accepts@1.0.7",
"dist": { "dist": {
"shasum": "fc9be3e5812513c8e758ea54d87f07275a5529d5" "shasum": "85a518a6fac930ecd86ae82149202b4f4ab842da"
}, },
"_from": "accepts@~1.0.5", "_from": "accepts@~1.0.7",
"_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.0.6.tgz" "_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.0.7.tgz"
} }
...@@ -24,5 +24,6 @@ ...@@ -24,5 +24,6 @@
"url": "https://github.com/component/escape-html/issues" "url": "https://github.com/component/escape-html/issues"
}, },
"_id": "escape-html@1.0.1", "_id": "escape-html@1.0.1",
"_from": "escape-html@1.0.1" "_from": "escape-html@1.0.1",
"scripts": {}
} }
4.5.0 / 2014-07-04
==================
* add deprecation message to non-plural `req.accepts*`
* add deprecation message to `res.send(body, status)`
* add deprecation message to `res.vary()`
* add `headers` option to `res.sendfile`
- use to set headers on successful file transfer
* add `mergeParams` option to `Router`
- merges `req.params` from parent routes
* add `req.hostname` -- correct name for what `req.host` returns
* deprecate things with `depd` module
* deprecate `req.host` -- use `req.hostname` instead
* fix behavior when handling request without routes
* fix handling when `route.all` is only route
* invoke `router.param()` only when route matches
* restore `req.params` after invoking router
* use `finalhandler` for final response handling
* use `media-typer` to alter content-type charset
* deps: accepts@~1.0.7
* deps: send@0.5.0
- Accept string for `maxage` (converted by `ms`)
- Include link in default redirect response
* deps: serve-static@~1.3.0
- Accept string for `maxAge` (converted by `ms`)
- Add `setHeaders` option
- Include HTML link in redirect response
- deps: send@0.5.0
* deps: type-is@~1.3.2
4.4.5 / 2014-06-26 4.4.5 / 2014-06-26
================== ==================
...@@ -202,6 +232,67 @@ ...@@ -202,6 +232,67 @@
- `app.route()` - Proxy to the app's `Router#route()` method to create a new route - `app.route()` - Proxy to the app's `Router#route()` method to create a new route
- Router & Route - public API - Router & Route - public API
3.13.0 / 2014-07-03
===================
* add deprecation message to `app.configure`
* add deprecation message to `req.auth`
* use `basic-auth` to parse `Authorization` header
* deps: connect@2.22.0
- deps: csurf@~1.3.0
- deps: express-session@~1.6.1
- deps: multiparty@3.3.0
- deps: serve-static@~1.3.0
* deps: send@0.5.0
- Accept string for `maxage` (converted by `ms`)
- Include link in default redirect response
3.12.1 / 2014-06-26
===================
* deps: connect@2.21.1
- deps: cookie-parser@1.3.2
- deps: cookie-signature@1.0.4
- deps: express-session@~1.5.2
- deps: type-is@~1.3.2
* deps: cookie-signature@1.0.4
- fix for timing attacks
3.12.0 / 2014-06-21
===================
* use `media-typer` to alter content-type charset
* deps: connect@2.21.0
- deprecate `connect(middleware)` -- use `app.use(middleware)` instead
- deprecate `connect.createServer()` -- use `connect()` instead
- fix `res.setHeader()` patch to work with with get -> append -> set pattern
- deps: compression@~1.0.8
- deps: errorhandler@~1.1.1
- deps: express-session@~1.5.0
- deps: serve-index@~1.1.3
3.11.0 / 2014-06-19
===================
* deprecate things with `depd` module
* deps: buffer-crc32@0.2.3
* deps: connect@2.20.2
- deprecate `verify` option to `json` -- use `body-parser` module directly
- deprecate `verify` option to `urlencoded` -- use `body-parser` module directly
- deprecate things with `depd` module
- use `finalhandler` for final response handling
- use `media-typer` to parse `content-type` for charset
- deps: body-parser@1.4.3
- deps: connect-timeout@1.1.1
- deps: cookie-parser@1.3.1
- deps: csurf@1.2.2
- deps: errorhandler@1.1.0
- deps: express-session@1.4.0
- deps: multiparty@3.2.9
- deps: serve-index@1.1.2
- deps: type-is@1.3.1
- deps: vhost@2.0.0
3.10.5 / 2014-06-11 3.10.5 / 2014-06-11
=================== ===================
......
[![express logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](http://expressjs.com/) [![Express Logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](https://expressjs.com/)
Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). Fast, unopinionated, minimalist web framework for [node](https://nodejs.org).
[![NPM version](https://badge.fury.io/js/express.svg)](http://badge.fury.io/js/express) [![NPM Version](https://badge.fury.io/js/express.svg)](https://badge.fury.io/js/express)
[![Build Status](https://travis-ci.org/visionmedia/express.svg?branch=master)](https://travis-ci.org/visionmedia/express) [![Build Status](https://travis-ci.org/visionmedia/express.svg?branch=master)](https://travis-ci.org/visionmedia/express)
[![Coverage Status](https://img.shields.io/coveralls/visionmedia/express.svg)](https://coveralls.io/r/visionmedia/express) [![Coverage Status](https://img.shields.io/coveralls/visionmedia/express.svg)](https://coveralls.io/r/visionmedia/express)
[![Gittip](http://img.shields.io/gittip/visionmedia.svg)](https://www.gittip.com/visionmedia/) [![Gittip](https://img.shields.io/gittip/visionmedia.svg)](https://www.gittip.com/visionmedia/)
```js ```js
var express = require('express'); var express = require('express')
var app = express(); var app = express()
app.get('/', function(req, res){ app.get('/', function (req, res) {
res.send('Hello World'); res.send('Hello World')
}); })
app.listen(3000); app.listen(3000)
``` ```
**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/visionmedia/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/visionmedia/express/wiki/New-features-in-4.x). **PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/visionmedia/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/visionmedia/express/wiki/New-features-in-4.x).
## Installation ### Installation
$ npm install express ```bash
$ npm install express
```
## Quick Start ## Quick Start
The quickest way to get started with express is to utilize the executable [`express(1)`](http://github.com/expressjs/generator) to generate an application as shown below: The quickest way to get started with express is to utilize the executable [`express(1)`](https://github.com/expressjs/generator) to generate an application as shown below:
Install the executable. The executable's major version will match Express's: Install the executable. The executable's major version will match Express's:
$ npm install -g express-generator@3
Create the app: ```bash
$ npm install -g express-generator@4
```
$ express /tmp/foo && cd /tmp/foo Create the app:
```bash
$ express /tmp/foo && cd /tmp/foo
```
Install dependencies: Install dependencies:
$ npm install ```bash
$ npm install
```
Start the server: Start the server:
$ npm start ```bash
$ npm start
```
## Features ## Features
...@@ -61,53 +71,57 @@ app.listen(3000); ...@@ -61,53 +71,57 @@ app.listen(3000);
HTTP APIs. HTTP APIs.
Express does not force you to use any specific ORM or template engine. With support for over Express does not force you to use any specific ORM or template engine. With support for over
14 template engines via [Consolidate.js](http://github.com/visionmedia/consolidate.js), 14 template engines via [Consolidate.js](https://github.com/visionmedia/consolidate.js),
you can quickly craft your perfect framework. you can quickly craft your perfect framework.
## More Information ## More Information
* [Website and Documentation](http://expressjs.com/) stored at [visionmedia/expressjs.com](https://github.com/visionmedia/expressjs.com) * [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/visionmedia/expressjs.com)]
* Join #express on freenode * [Github Organization](https://github.com/expressjs) for Official Middleware & Modules
* [Google Group](http://groups.google.com/group/express-js) for discussion * [#express](https://webchat.freenode.net/?channels=express) on freenode IRC
* Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) and [defunctzombie](https://twitter.com/defunctzombie) on twitter for updates * Visit the [Wiki](https://github.com/visionmedia/express/wiki)
* Visit the [Wiki](http://github.com/visionmedia/express/wiki) * [Google Group](https://groups.google.com/group/express-js) for discussion
* [Русскоязычная документация](http://jsman.ru/express/) * [Русскоязычная документация](http://jsman.ru/express/)
* Run express examples [online](https://runnable.com/express) * Run express examples [online](https://runnable.com/express)
## Viewing Examples ## Viewing Examples
Clone the Express repo, then install the dev dependencies to install all the example / test suite dependencies: Clone the Express repo, then install the dev dependencies to install all the example / test suite dependencies:
$ git clone git://github.com/visionmedia/express.git --depth 1 ```bash
$ cd express $ git clone git://github.com/visionmedia/express.git --depth 1
$ npm install $ cd express
$ npm install
```
Then run whichever tests you want: Then run whichever example you want:
$ node examples/content-negotiation $ node examples/content-negotiation
You can also view live examples here: You can also view live examples here:
<a href="https://runnable.com/express" target="_blank"><img src="https://runnable.com/external/styles/assets/runnablebtn.png" style="width:67px;height:25px;"></a> <a href="https://runnable.com/express" target="_blank"><img src="https://runnable.com/external/styles/assets/runnablebtn.png" style="width:67px;height:25px;"></a>
## Running Tests ## Running Tests
To run the test suite, first invoke the following command within the repo, installing the development dependencies: To run the test suite, first invoke the following command within the repo, installing the development dependencies:
$ npm install ```bash
$ npm install
```
Then run the tests: Then run the tests:
```sh ```bash
$ npm test $ npm test
``` ```
## Contributors ### Contributors
Author: [TJ Holowaychuk](http://github.com/visionmedia) * Author: [TJ Holowaychuk](https://github.com/visionmedia)
Lead Maintainer: [Roman Shtylman](https://github.com/defunctzombie) * Lead Maintainer: [Douglas Christopher Wilson](https://github.com/dougwilson)
Contributors: https://github.com/visionmedia/express/graphs/contributors * [All Contributors](https://github.com/visionmedia/express/graphs/contributors)
## License ### License
MIT [MIT](LICENSE)
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
* Module dependencies. * Module dependencies.
*/ */
var finalhandler = require('finalhandler');
var mixin = require('utils-merge'); var mixin = require('utils-merge');
var escapeHtml = require('escape-html');
var Router = require('./router'); var Router = require('./router');
var methods = require('methods'); var methods = require('methods');
var middleware = require('./middleware/init'); var middleware = require('./middleware/init');
...@@ -13,7 +13,7 @@ var View = require('./view'); ...@@ -13,7 +13,7 @@ var View = require('./view');
var http = require('http'); var http = require('http');
var compileETag = require('./utils').compileETag; var compileETag = require('./utils').compileETag;
var compileTrust = require('./utils').compileTrust; var compileTrust = require('./utils').compileTrust;
var deprecate = require('./utils').deprecate; var deprecate = require('depd')('express');
var resolve = require('path').resolve; var resolve = require('path').resolve;
/** /**
...@@ -119,45 +119,22 @@ app.lazyrouter = function() { ...@@ -119,45 +119,22 @@ app.lazyrouter = function() {
*/ */
app.handle = function(req, res, done) { app.handle = function(req, res, done) {
var env = this.get('env'); var router = this._router;
this._router.handle(req, res, function(err) { // final handler
if (done) { done = done || finalhandler(req, res, {
return done(err); env: this.get('env'),
} onerror: logerror.bind(this)
});
// unhandled error // no routes
if (err) { if (!router) {
// default to 500 debug('no routes defined on app');
if (res.statusCode < 400) res.statusCode = 500; done();
debug('default %s', res.statusCode); return;
}
// respect err.status
if (err.status) res.statusCode = err.status;
// production gets a basic error message
var msg = 'production' == env
? http.STATUS_CODES[res.statusCode]
: err.stack || err.toString();
msg = escapeHtml(msg);
// log to stderr in a non-test env
if ('test' != env) console.error(err.stack || err.toString());
if (res.headersSent) return req.socket.destroy();
res.setHeader('Content-Type', 'text/html');
res.setHeader('Content-Length', Buffer.byteLength(msg));
if ('HEAD' == req.method) return res.end();
res.end(msg);
return;
}
// 404 router.handle(req, res, done);
debug('default 404');
res.statusCode = 404;
res.setHeader('Content-Type', 'text/html');
if ('HEAD' == req.method) return res.end();
res.end('Cannot ' + escapeHtml(req.method) + ' ' + escapeHtml(req.originalUrl) + '\n');
});
}; };
/** /**
...@@ -449,7 +426,7 @@ app.all = function(path){ ...@@ -449,7 +426,7 @@ app.all = function(path){
// del -> delete alias // del -> delete alias
app.del = deprecate(app.delete, 'app.del: Use app.delete instead'); app.del = deprecate.function(app.delete, 'app.del: Use app.delete instead');
/** /**
* Render the given view `name` name with `options` * Render the given view `name` name with `options`
...@@ -547,3 +524,14 @@ app.listen = function(){ ...@@ -547,3 +524,14 @@ app.listen = function(){
var server = http.createServer(this); var server = http.createServer(this);
return server.listen.apply(server, arguments); return server.listen.apply(server, arguments);
}; };
/**
* Log error using console.error.
*
* @param {Error} err
* @api public
*/
function logerror(err){
if (this.get('env') !== 'test') console.error(err.stack || err.toString());
}
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
*/ */
var accepts = require('accepts'); var accepts = require('accepts');
var deprecate = require('depd')('express');
var typeis = require('type-is'); var typeis = require('type-is');
var http = require('http'); var http = require('http');
var fresh = require('fresh'); var fresh = require('fresh');
...@@ -106,53 +107,55 @@ req.accepts = function(){ ...@@ -106,53 +107,55 @@ req.accepts = function(){
}; };
/** /**
* Check if the given `encoding` is accepted. * Check if the given `encoding`s are accepted.
* *
* @param {String} encoding * @param {String} ...encoding
* @return {Boolean} * @return {Boolean}
* @api public * @api public
*/ */
req.acceptsEncoding = // backwards compatibility
req.acceptsEncodings = function(){ req.acceptsEncodings = function(){
var accept = accepts(this); var accept = accepts(this);
return accept.encodings.apply(accept, arguments); return accept.encodings.apply(accept, arguments);
}; };
req.acceptsEncoding = deprecate.function(req.acceptsEncodings,
'req.acceptsEncoding: Use acceptsEncodings instead');
/** /**
* To do: update docs. * Check if the given `charset`s are acceptable,
*
* Check if the given `charset` is acceptable,
* otherwise you should respond with 406 "Not Acceptable". * otherwise you should respond with 406 "Not Acceptable".
* *
* @param {String} charset * @param {String} ...charset
* @return {Boolean} * @return {Boolean}
* @api public * @api public
*/ */
req.acceptsCharset = // backwards compatibility
req.acceptsCharsets = function(){ req.acceptsCharsets = function(){
var accept = accepts(this); var accept = accepts(this);
return accept.charsets.apply(accept, arguments); return accept.charsets.apply(accept, arguments);
}; };
req.acceptsCharset = deprecate.function(req.acceptsCharsets,
'req.acceptsCharset: Use acceptsCharsets instead');
/** /**
* To do: update docs. * Check if the given `lang`s are acceptable,
*
* Check if the given `lang` is acceptable,
* otherwise you should respond with 406 "Not Acceptable". * otherwise you should respond with 406 "Not Acceptable".
* *
* @param {String} lang * @param {String} ...lang
* @return {Boolean} * @return {Boolean}
* @api public * @api public
*/ */
req.acceptsLanguage = // backwards compatibility
req.acceptsLanguages = function(){ req.acceptsLanguages = function(){
var accept = accepts(this); var accept = accepts(this);
return accept.languages.apply(accept, arguments); return accept.languages.apply(accept, arguments);
}; };
req.acceptsLanguage = deprecate.function(req.acceptsLanguages,
'req.acceptsLanguage: Use acceptsLanguages instead');
/** /**
* Parse Range header field, * Parse Range header field,
* capping to the given `size`. * capping to the given `size`.
...@@ -249,7 +252,7 @@ req.is = function(types){ ...@@ -249,7 +252,7 @@ req.is = function(types){
* @api public * @api public
*/ */
req.__defineGetter__('protocol', function(){ defineGetter(req, 'protocol', function protocol(){
var trust = this.app.get('trust proxy fn'); var trust = this.app.get('trust proxy fn');
if (!trust(this.connection.remoteAddress)) { if (!trust(this.connection.remoteAddress)) {
...@@ -273,7 +276,7 @@ req.__defineGetter__('protocol', function(){ ...@@ -273,7 +276,7 @@ req.__defineGetter__('protocol', function(){
* @api public * @api public
*/ */
req.__defineGetter__('secure', function(){ defineGetter(req, 'secure', function secure(){
return 'https' == this.protocol; return 'https' == this.protocol;
}); });
...@@ -287,7 +290,7 @@ req.__defineGetter__('secure', function(){ ...@@ -287,7 +290,7 @@ req.__defineGetter__('secure', function(){
* @api public * @api public
*/ */
req.__defineGetter__('ip', function(){ defineGetter(req, 'ip', function ip(){
var trust = this.app.get('trust proxy fn'); var trust = this.app.get('trust proxy fn');
return proxyaddr(this, trust); return proxyaddr(this, trust);
}); });
...@@ -304,7 +307,7 @@ req.__defineGetter__('ip', function(){ ...@@ -304,7 +307,7 @@ req.__defineGetter__('ip', function(){
* @api public * @api public
*/ */
req.__defineGetter__('ips', function(){ defineGetter(req, 'ips', function ips() {
var trust = this.app.get('trust proxy fn'); var trust = this.app.get('trust proxy fn');
var addrs = proxyaddr.all(this, trust); var addrs = proxyaddr.all(this, trust);
return addrs.slice(1).reverse(); return addrs.slice(1).reverse();
...@@ -325,9 +328,9 @@ req.__defineGetter__('ips', function(){ ...@@ -325,9 +328,9 @@ req.__defineGetter__('ips', function(){
* @api public * @api public
*/ */
req.__defineGetter__('subdomains', function(){ defineGetter(req, 'subdomains', function subdomains() {
var offset = this.app.get('subdomain offset'); var offset = this.app.get('subdomain offset');
return (this.host || '') return (this.hostname || '')
.split('.') .split('.')
.reverse() .reverse()
.slice(offset); .slice(offset);
...@@ -340,12 +343,12 @@ req.__defineGetter__('subdomains', function(){ ...@@ -340,12 +343,12 @@ req.__defineGetter__('subdomains', function(){
* @api public * @api public
*/ */
req.__defineGetter__('path', function(){ defineGetter(req, 'path', function path() {
return parse(this).pathname; return parse(this).pathname;
}); });
/** /**
* Parse the "Host" header field hostname. * Parse the "Host" header field to a hostname.
* *
* When the "trust proxy" setting trusts the socket * When the "trust proxy" setting trusts the socket
* address, the "X-Forwarded-Host" header field will * address, the "X-Forwarded-Host" header field will
...@@ -355,7 +358,7 @@ req.__defineGetter__('path', function(){ ...@@ -355,7 +358,7 @@ req.__defineGetter__('path', function(){
* @api public * @api public
*/ */
req.__defineGetter__('host', function(){ defineGetter(req, 'hostname', function hostname(){
var trust = this.app.get('trust proxy fn'); var trust = this.app.get('trust proxy fn');
var host = this.get('X-Forwarded-Host'); var host = this.get('X-Forwarded-Host');
...@@ -376,6 +379,12 @@ req.__defineGetter__('host', function(){ ...@@ -376,6 +379,12 @@ req.__defineGetter__('host', function(){
: host; : host;
}); });
// TODO: change req.host to return host in next major
defineGetter(req, 'host', deprecate.function(function host(){
return this.hostname;
}, 'req.host: Use req.hostname instead'));
/** /**
* Check if the request is fresh, aka * Check if the request is fresh, aka
* Last-Modified and/or the ETag * Last-Modified and/or the ETag
...@@ -385,7 +394,7 @@ req.__defineGetter__('host', function(){ ...@@ -385,7 +394,7 @@ req.__defineGetter__('host', function(){
* @api public * @api public
*/ */
req.__defineGetter__('fresh', function(){ defineGetter(req, 'fresh', function(){
var method = this.method; var method = this.method;
var s = this.res.statusCode; var s = this.res.statusCode;
...@@ -409,7 +418,7 @@ req.__defineGetter__('fresh', function(){ ...@@ -409,7 +418,7 @@ req.__defineGetter__('fresh', function(){
* @api public * @api public
*/ */
req.__defineGetter__('stale', function(){ defineGetter(req, 'stale', function stale(){
return !this.fresh; return !this.fresh;
}); });
...@@ -420,7 +429,23 @@ req.__defineGetter__('stale', function(){ ...@@ -420,7 +429,23 @@ req.__defineGetter__('stale', function(){
* @api public * @api public
*/ */
req.__defineGetter__('xhr', function(){ defineGetter(req, 'xhr', function xhr(){
var val = this.get('X-Requested-With') || ''; var val = this.get('X-Requested-With') || '';
return 'xmlhttprequest' == val.toLowerCase(); return 'xmlhttprequest' == val.toLowerCase();
}); });
/**
* Helper function for creating a getter on an object.
*
* @param {Object} obj
* @param {String} name
* @param {Function} getter
* @api private
*/
function defineGetter(obj, name, getter) {
Object.defineProperty(obj, name, {
configurable: true,
enumerable: true,
get: getter
});
};
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Module dependencies. * Module dependencies.
*/ */
var deprecate = require('depd')('express');
var escapeHtml = require('escape-html'); var escapeHtml = require('escape-html');
var http = require('http'); var http = require('http');
var path = require('path'); var path = require('path');
...@@ -11,7 +12,6 @@ var normalizeType = require('./utils').normalizeType; ...@@ -11,7 +12,6 @@ var normalizeType = require('./utils').normalizeType;
var normalizeTypes = require('./utils').normalizeTypes; var normalizeTypes = require('./utils').normalizeTypes;
var setCharset = require('./utils').setCharset; var setCharset = require('./utils').setCharset;
var contentDisposition = require('./utils').contentDisposition; var contentDisposition = require('./utils').contentDisposition;
var deprecate = require('./utils').deprecate;
var statusCodes = http.STATUS_CODES; var statusCodes = http.STATUS_CODES;
var cookie = require('cookie'); var cookie = require('cookie');
var send = require('send'); var send = require('send');
...@@ -92,6 +92,7 @@ res.send = function(body){ ...@@ -92,6 +92,7 @@ res.send = function(body){
if (2 == arguments.length) { if (2 == arguments.length) {
// res.send(body, status) backwards compat // res.send(body, status) backwards compat
if ('number' != typeof body && 'number' == typeof arguments[1]) { if ('number' != typeof body && 'number' == typeof arguments[1]) {
deprecate('res.send(body, status): Use res.send(status, body) instead');
this.statusCode = arguments[1]; this.statusCode = arguments[1];
} else { } else {
this.statusCode = body; this.statusCode = body;
...@@ -186,9 +187,11 @@ res.json = function(obj){ ...@@ -186,9 +187,11 @@ res.json = function(obj){
// res.json(body, status) backwards compat // res.json(body, status) backwards compat
if ('number' == typeof arguments[1]) { if ('number' == typeof arguments[1]) {
this.statusCode = arguments[1]; this.statusCode = arguments[1];
return 'number' === typeof obj if (typeof obj === 'number') {
? jsonNumDeprecated.call(this, obj) deprecate('res.json(obj, status): Use res.json(status, obj) instead');
: jsonDeprecated.call(this, obj); } else {
deprecate('res.json(num, status): Use res.status(status).json(num) instead');
}
} else { } else {
this.statusCode = obj; this.statusCode = obj;
obj = arguments[1]; obj = arguments[1];
...@@ -207,12 +210,6 @@ res.json = function(obj){ ...@@ -207,12 +210,6 @@ res.json = function(obj){
return this.send(body); return this.send(body);
}; };
var jsonDeprecated = deprecate(res.json,
'res.json(obj, status): Use res.json(status, obj) instead');
var jsonNumDeprecated = deprecate(res.json,
'res.json(num, status): Use res.status(status).json(num) instead');
/** /**
* Send JSON response with JSONP callback support. * Send JSON response with JSONP callback support.
* *
...@@ -232,9 +229,11 @@ res.jsonp = function(obj){ ...@@ -232,9 +229,11 @@ res.jsonp = function(obj){
// res.json(body, status) backwards compat // res.json(body, status) backwards compat
if ('number' == typeof arguments[1]) { if ('number' == typeof arguments[1]) {
this.statusCode = arguments[1]; this.statusCode = arguments[1];
return 'number' === typeof obj if (typeof obj === 'number') {
? jsonpNumDeprecated.call(this, obj) deprecate('res.jsonp(obj, status): Use res.jsonp(status, obj) instead');
: jsonpDeprecated.call(this, obj); } else {
deprecate('res.jsonp(num, status): Use res.status(status).jsonp(num) instead');
}
} else { } else {
this.statusCode = obj; this.statusCode = obj;
obj = arguments[1]; obj = arguments[1];
...@@ -268,12 +267,6 @@ res.jsonp = function(obj){ ...@@ -268,12 +267,6 @@ res.jsonp = function(obj){
return this.send(body); return this.send(body);
}; };
var jsonpDeprecated = deprecate(res.json,
'res.jsonp(obj, status): Use res.jsonp(status, obj) instead');
var jsonpNumDeprecated = deprecate(res.json,
'res.jsonp(num, status): Use res.status(status).jsonp(num) instead');
/** /**
* Transfer the file at the given `path`. * Transfer the file at the given `path`.
* *
...@@ -285,9 +278,10 @@ var jsonpNumDeprecated = deprecate(res.json, ...@@ -285,9 +278,10 @@ var jsonpNumDeprecated = deprecate(res.json,
* *
* Options: * Options:
* *
* - `maxAge` defaulting to 0 * - `maxAge` defaulting to 0 (can be string converted by `ms`)
* - `root` root directory for relative filenames * - `root` root directory for relative filenames
* - `hidden` serve hidden files, defaulting to false * - `headers` object of headers to serve with file
* - `hidden` serve hidden files, defaulting to false
* *
* Other options are passed along to `send`. * Other options are passed along to `send`.
* *
...@@ -338,14 +332,10 @@ res.sendfile = function(path, options, fn){ ...@@ -338,14 +332,10 @@ res.sendfile = function(path, options, fn){
// clean up // clean up
cleanup(); cleanup();
if (!self.headersSent) self.removeHeader('Content-Disposition');
// callback available // callback available
if (fn) return fn(err); if (fn) return fn(err);
// list in limbo if there's no callback
if (self.headersSent) return;
// delegate // delegate
next(err); next(err);
} }
...@@ -370,6 +360,21 @@ res.sendfile = function(path, options, fn){ ...@@ -370,6 +360,21 @@ res.sendfile = function(path, options, fn){
file.on('error', error); file.on('error', error);
file.on('directory', next); file.on('directory', next);
file.on('stream', stream); file.on('stream', stream);
if (options.headers) {
// set headers on successful transfer
file.on('headers', function headers(res) {
var obj = options.headers;
var keys = Object.keys(obj);
for (var i = 0; i < keys.length; i++) {
var k = keys[i];
res.setHeader(k, obj[k]);
}
});
}
// pipe
file.pipe(this); file.pipe(this);
this.on('finish', cleanup); this.on('finish', cleanup);
}; };
...@@ -395,8 +400,13 @@ res.download = function(path, filename, fn){ ...@@ -395,8 +400,13 @@ res.download = function(path, filename, fn){
} }
filename = filename || path; filename = filename || path;
this.set('Content-Disposition', contentDisposition(filename));
return this.sendfile(path, fn); // set Content-Disposition when file is sent
var headers = {
'Content-Disposition': contentDisposition(filename)
};
return this.sendfile(path, { headers: headers }, fn);
}; };
/** /**
...@@ -737,8 +747,10 @@ res.redirect = function(url){ ...@@ -737,8 +747,10 @@ res.redirect = function(url){
res.vary = function(field){ res.vary = function(field){
// checks for back-compat // checks for back-compat
if (!field) return this; if (!field || (Array.isArray(field) && !field.length)) {
if (Array.isArray(field) && !field.length) return this; deprecate('res.vary(): Provide a field name');
return this;
}
vary(this, field); vary(this, field);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
var Route = require('./route'); var Route = require('./route');
var Layer = require('./layer'); var Layer = require('./layer');
var methods = require('methods'); var methods = require('methods');
var mixin = require('utils-merge');
var debug = require('debug')('express:router'); var debug = require('debug')('express:router');
var parseUrl = require('parseurl'); var parseUrl = require('parseurl');
var slice = Array.prototype.slice; var slice = Array.prototype.slice;
...@@ -30,6 +31,7 @@ var proto = module.exports = function(options) { ...@@ -30,6 +31,7 @@ var proto = module.exports = function(options) {
router.params = {}; router.params = {};
router._params = []; router._params = [];
router.caseSensitive = options.caseSensitive; router.caseSensitive = options.caseSensitive;
router.mergeParams = options.mergeParams;
router.strict = options.strict; router.strict = options.strict;
router.stack = []; router.stack = [];
...@@ -132,13 +134,11 @@ proto.handle = function(req, res, done) { ...@@ -132,13 +134,11 @@ proto.handle = function(req, res, done) {
var stack = self.stack; var stack = self.stack;
// manage inter-router variables // manage inter-router variables
var parent = req.next; var parentParams = req.params;
var parentUrl = req.baseUrl || ''; var parentUrl = req.baseUrl || '';
done = wrap(done, function(old, err) { done = restore(done, req, 'baseUrl', 'next', 'params');
req.baseUrl = parentUrl;
req.next = parent; // setup next layer
old(err);
});
req.next = next; req.next = next;
// for options requests, respond with a default if nothing else responds // for options requests, respond with a default if nothing else responds
...@@ -191,16 +191,26 @@ proto.handle = function(req, res, done) { ...@@ -191,16 +191,26 @@ proto.handle = function(req, res, done) {
return next(err); return next(err);
} }
req.route = route; var has_method = route._handles_method(method);
// we can now dispatch to the route // build up automatic options response
if (method === 'options' && !route.methods['options']) { if (!has_method && method === 'options') {
options.push.apply(options, route._options()); options.push.apply(options, route._options());
} }
// don't even bother
if (!has_method && method !== 'head') {
return next();
}
// we can now dispatch to the route
req.route = route;
} }
// Capture one-time layer values // Capture one-time layer values
req.params = layer.params; req.params = self.mergeParams
? mergeParams(layer.params, parentParams)
: layer.params;
layerPath = layer.path; layerPath = layer.path;
// this should be done for the layer // this should be done for the layer
...@@ -260,13 +270,6 @@ proto.handle = function(req, res, done) { ...@@ -260,13 +270,6 @@ proto.handle = function(req, res, done) {
} }
} }
} }
function wrap(old, fn) {
return function () {
var args = [old].concat(slice.call(arguments));
fn.apply(this, args);
};
}
}; };
/** /**
...@@ -450,3 +453,67 @@ methods.concat('all').forEach(function(method){ ...@@ -450,3 +453,67 @@ methods.concat('all').forEach(function(method){
return this; return this;
}; };
}); });
// merge params with parent params
function mergeParams(params, parent) {
if (typeof parent !== 'object' || !parent) {
return params;
}
// make copy of parent for base
var obj = mixin({}, parent);
// simple non-numeric merging
if (!(0 in params) || !(0 in parent)) {
return mixin(obj, params);
}
var i = 0;
var o = 0;
// determine numeric gaps
while (i === o || o in parent) {
if (i in params) i++;
if (o in parent) o++;
}
// offset numeric indices in params before merge
for (i--; i >= 0; i--) {
params[i + o] = params[i];
// create holes for the merge when necessary
if (i < o) {
delete params[i];
}
}
return mixin(parent, params);
}
// restore obj props after function
function restore(fn, obj) {
var props = new Array(arguments.length - 2);
var vals = new Array(arguments.length - 2);
for (var i = 0; i < props.length; i++) {
props[i] = arguments[i + 2];
vals[i] = obj[props[i]];
}
return function(err){
// restore vals
for (var i = 0; i < props.length; i++) {
obj[props[i]] = vals[i];
}
return fn.apply(this, arguments);
};
}
// wrap a function
function wrap(old, fn) {
return function () {
var args = [old].concat(slice.call(arguments));
fn.apply(this, args);
};
}
...@@ -45,16 +45,7 @@ Layer.prototype.match = function(path){ ...@@ -45,16 +45,7 @@ Layer.prototype.match = function(path){
for (var i = 1, len = m.length; i < len; ++i) { for (var i = 1, len = m.length; i < len; ++i) {
key = keys[i - 1]; key = keys[i - 1];
val = decode_param(m[i]);
try {
val = 'string' == typeof m[i]
? decodeURIComponent(m[i])
: m[i];
} catch(e) {
var err = new Error("Failed to decode param '" + m[i] + "'");
err.status = 400;
throw err;
}
if (key) { if (key) {
params[key.name] = val; params[key.name] = val;
...@@ -65,3 +56,25 @@ Layer.prototype.match = function(path){ ...@@ -65,3 +56,25 @@ Layer.prototype.match = function(path){
return true; return true;
}; };
/**
* Decode param value.
*
* @param {string} val
* @return {string}
* @api private
*/
function decode_param(val){
if (typeof val !== 'string') {
return val;
}
try {
return decodeURIComponent(val);
} catch (e) {
var err = new TypeError("Failed to decode param '" + val + "'");
err.status = 400;
throw err;
}
}
...@@ -22,12 +22,30 @@ module.exports = Route; ...@@ -22,12 +22,30 @@ module.exports = Route;
function Route(path) { function Route(path) {
debug('new %s', path); debug('new %s', path);
this.path = path; this.path = path;
this.stack = undefined; this.stack = [];
// route handlers for various http methods // route handlers for various http methods
this.methods = {}; this.methods = {};
} }
/**
* @api private
*/
Route.prototype._handles_method = function _handles_method(method) {
if (this.methods._all) {
return true;
}
method = method.toLowerCase();
if (method === 'head' && !this.methods['head']) {
method = 'get';
}
return Boolean(this.methods[method]);
};
/** /**
* @return {Array} supported HTTP methods * @return {Array} supported HTTP methods
* @api private * @api private
...@@ -46,25 +64,17 @@ Route.prototype._options = function(){ ...@@ -46,25 +64,17 @@ Route.prototype._options = function(){
*/ */
Route.prototype.dispatch = function(req, res, done){ Route.prototype.dispatch = function(req, res, done){
var self = this; var stack = this.stack;
var method = req.method.toLowerCase(); if (stack.length === 0) {
return done();
}
var method = req.method.toLowerCase();
if (method === 'head' && !this.methods['head']) { if (method === 'head' && !this.methods['head']) {
method = 'get'; method = 'get';
} }
req.route = self; req.route = this;
// single middleware route case
if (typeof this.stack === 'function') {
this.stack(req, res, done);
return;
}
var stack = self.stack;
if (!stack) {
return done();
}
var idx = 0; var idx = 0;
(function next_layer(err) { (function next_layer(err) {
...@@ -145,15 +155,8 @@ Route.prototype.all = function(){ ...@@ -145,15 +155,8 @@ Route.prototype.all = function(){
throw new Error(msg); throw new Error(msg);
} }
if (!self.stack) { self.methods._all = true;
self.stack = fn; self.stack.push({ handle: fn });
}
else if (typeof self.stack === 'function') {
self.stack = [{ handle: self.stack }, { handle: fn }];
}
else {
self.stack.push({ handle: fn });
}
}); });
return self; return self;
...@@ -177,13 +180,6 @@ methods.forEach(function(method){ ...@@ -177,13 +180,6 @@ methods.forEach(function(method){
self.methods[method] = true; self.methods[method] = true;
} }
if (!self.stack) {
self.stack = [];
}
else if (typeof self.stack === 'function') {
self.stack = [{ handle: self.stack }];
}
self.stack.push({ method: method, handle: fn }); self.stack.push({ method: method, handle: fn });
}); });
return self; return self;
......
...@@ -6,37 +6,8 @@ var mime = require('send').mime; ...@@ -6,37 +6,8 @@ var mime = require('send').mime;
var crc32 = require('buffer-crc32'); var crc32 = require('buffer-crc32');
var crypto = require('crypto'); var crypto = require('crypto');
var basename = require('path').basename; var basename = require('path').basename;
var deprecate = require('util').deprecate;
var proxyaddr = require('proxy-addr'); var proxyaddr = require('proxy-addr');
var typer = require('media-typer');
/**
* Simple detection of charset parameter in content-type
*/
var charsetRegExp = /;\s*charset\s*=/;
/**
* Deprecate function, like core `util.deprecate`,
* but with NODE_ENV and color support.
*
* @param {Function} fn
* @param {String} msg
* @return {Function}
* @api private
*/
exports.deprecate = function(fn, msg){
if (process.env.NODE_ENV === 'test') return fn;
// prepend module name
msg = 'express: ' + msg;
if (process.stderr.isTTY) {
// colorize
msg = '\x1b[31;1m' + msg + '\x1b[0m';
}
return deprecate(fn, msg);
};
/** /**
* Return strong ETag for `body`. * Return strong ETag for `body`.
...@@ -272,21 +243,12 @@ exports.compileTrust = function(val) { ...@@ -272,21 +243,12 @@ exports.compileTrust = function(val) {
exports.setCharset = function(type, charset){ exports.setCharset = function(type, charset){
if (!type || !charset) return type; if (!type || !charset) return type;
var exists = charsetRegExp.test(type); // parse type
var parsed = typer.parse(type);
// removing existing charset // set charset
if (exists) { parsed.parameters.charset = charset;
var parts = type.split(';');
for (var i = 1; i < parts.length; i++) {
if (charsetRegExp.test(';' + parts[i])) {
parts.splice(i, 1);
break;
}
}
type = parts.join(';');
}
return type + '; charset=' + charset; // format type
return typer.format(parsed);
}; };
1.0.7 / 2014-07-04
==================
* Fix wrong type returned from `type` when match after unknown extension
1.0.6 / 2014-06-24 1.0.6 / 2014-06-24
================== ==================
......
...@@ -60,8 +60,8 @@ Accepts.prototype.types = function (types) { ...@@ -60,8 +60,8 @@ Accepts.prototype.types = function (types) {
var n = this.negotiator; var n = this.negotiator;
if (!types.length) return n.mediaTypes(); if (!types.length) return n.mediaTypes();
if (!this.headers.accept) return types[0]; if (!this.headers.accept) return types[0];
var mimes = types.map(extToMime).filter(validMime); var mimes = types.map(extToMime);
var accepts = n.mediaTypes(mimes); var accepts = n.mediaTypes(mimes.filter(validMime));
var first = accepts[0]; var first = accepts[0];
if (!first) return false; if (!first) return false;
return types[mimes.indexOf(first)]; return types[mimes.indexOf(first)];
......
...@@ -45,9 +45,5 @@ ...@@ -45,9 +45,5 @@
}, },
"dependencies": {}, "dependencies": {},
"_id": "negotiator@0.4.7", "_id": "negotiator@0.4.7",
"dist": { "_from": "negotiator@0.4.7"
"shasum": "8273ad98ad1c14fed21daa9a404fb6a102d47305"
},
"_from": "negotiator@0.4.7",
"_resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.7.tgz"
} }
{ {
"name": "accepts", "name": "accepts",
"description": "Higher-level content negotiation", "description": "Higher-level content negotiation",
"version": "1.0.6", "version": "1.0.7",
"author": { "author": {
"name": "Jonathan Ong", "name": "Jonathan Ong",
"email": "me@jongleberry.com", "email": "me@jongleberry.com",
...@@ -34,10 +34,10 @@ ...@@ -34,10 +34,10 @@
"bugs": { "bugs": {
"url": "https://github.com/expressjs/accepts/issues" "url": "https://github.com/expressjs/accepts/issues"
}, },
"_id": "accepts@1.0.6", "_id": "accepts@1.0.7",
"dist": { "dist": {
"shasum": "fc9be3e5812513c8e758ea54d87f07275a5529d5" "shasum": "85a518a6fac930ecd86ae82149202b4f4ab842da"
}, },
"_from": "accepts@~1.0.5", "_from": "accepts@~1.0.5",
"_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.0.6.tgz" "_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.0.7.tgz"
} }
...@@ -27,9 +27,5 @@ ...@@ -27,9 +27,5 @@
"url": "https://github.com/visionmedia/node-cookie-signature/issues" "url": "https://github.com/visionmedia/node-cookie-signature/issues"
}, },
"_id": "cookie-signature@1.0.4", "_id": "cookie-signature@1.0.4",
"dist": { "_from": "cookie-signature@1.0.4"
"shasum": "aa3b73d0f90834fd3fea70fbab15819cd3ca1441"
},
"_from": "cookie-signature@1.0.4",
"_resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.4.tgz"
} }
...@@ -23,5 +23,9 @@ ...@@ -23,5 +23,9 @@
"url": "https://github.com/guille/ms.js/issues" "url": "https://github.com/guille/ms.js/issues"
}, },
"_id": "ms@0.6.2", "_id": "ms@0.6.2",
"_from": "ms@0.6.2" "dist": {
"shasum": "f13296ecf600d296c9f2ff2b61f2f9eb12a69c79"
},
"_from": "ms@0.6.2",
"_resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz"
} }
...@@ -43,9 +43,5 @@ ...@@ -43,9 +43,5 @@
"url": "https://github.com/visionmedia/debug/issues" "url": "https://github.com/visionmedia/debug/issues"
}, },
"_id": "debug@1.0.2", "_id": "debug@1.0.2",
"dist": { "_from": "debug@1.0.2"
"shasum": "a1c1da1278c90866cc063eff49db9f0a8a0a211e"
},
"_from": "debug@1.0.2",
"_resolved": "https://registry.npmjs.org/debug/-/debug-1.0.2.tgz"
} }
0.3.0 / 2014-06-16
==================
* Add `NO_DEPRECATION` environment variable
0.2.0 / 2014-06-15
==================
* Add `deprecate.property(obj, prop, message)`
* Remove `supports-color` dependency for node.js 0.8
0.1.0 / 2014-06-15
==================
* Add `deprecate.function(fn, message)`
* Add `process.on('deprecation', fn)` emitter
* Automatically generate message when omitted from `deprecate()`
0.0.1 / 2014-06-15
==================
* Fix warning for dynamic calls at singe call site
0.0.0 / 2014-06-15
==================
* Initial implementation
(The MIT License) (The MIT License)
Copyright (c) 2010 Sencha Inc.
Copyright (c) 2011 LearnBoost
Copyright (c) 2011 TJ Holowaychuk
Copyright (c) 2014 Douglas Christopher Wilson Copyright (c) 2014 Douglas Christopher Wilson
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
......
# depd
[![NPM version](https://badge.fury.io/js/depd.svg)](http://badge.fury.io/js/depd)
[![Build Status](https://travis-ci.org/dougwilson/nodejs-depd.svg?branch=master)](https://travis-ci.org/dougwilson/nodejs-depd)
[![Coverage Status](https://img.shields.io/coveralls/dougwilson/nodejs-depd.svg?branch=master)](https://coveralls.io/r/dougwilson/nodejs-depd)
Deprecate all the things
> With great modules comes great responsibility; mark things deprecated!
## Install
```sh
$ npm install depd
```
## API
```js
var depd = require('depd')
var deprecate = depd('my-module')
```
This library allows you to display deprecation messages to your users.
This library goes above and beyond with deprecation warnings by
introspecting the call stack (but only the bits that it is interested
in).
Instead of just warning on the first invocation of a deprecated
function and never again, this module will warn on the first invocation
of a deprecated function per unique call site, making it ideal to alert
users of all deprecated uses across the code base, rather than just
whatever happens to execute first.
The deprecation warnings from this module also include the file and line
information for the call into the module that the deprecated function was
in.
### depd(namespace)
Create a new deprecate function that uses the given namespace name in the
messages and will display the call site prior to the stack entering the
file this function was called from. It is highly suggested you use the
name of your module as the namespace.
### deprecate(message)
Call this function from deprecated code to display a deprecation message.
This message will appear once per unique caller site. Caller site is the
first call site in the stack in a different file from the caller of this
function.
If the message is omitted, a message is generated for you based on the site
of the `deprecate()` call and will display the name of the function called,
similar to the name displayed in a stack trace.
### deprecate.function(fn, message)
Call this function to wrap a given function in a deprecation message on any
call to the function. An optional message can be supplied to provide a custom
message.
### deprecate.property(obj, prop, message)
Call this function to wrap a given property on object in a deprecation message
on any accessing or setting of the property. An optional message can be supplied
to provide a custom message.
The method must be called on the object where the property belongs (not
inherited from the prototype).
If the property is a data descriptor, it will be converted to an accessor
descriptor in order to display the deprecation message.
### process.on('deprecation', fn)
This module will allow easy capturing of deprecation errors by emitting the
errors as the type "deprecation" on the global `process`. If there are no
listeners for this type, the errors are written to STDERR as normal, but if
there are any listeners, nothing will be written to STDERR and instead only
emitted. From there, you can write the errors in a different format or to a
logging source.
The error represents the deprecation and is emitted only once with the same
rules as writing to STDERR. The error has the following properties:
- `message` - This is the message given by the library
- `name` - This is always `'DeprecationError'`
- `namespace` - This is the namespace the deprecation came from
- `stack` - This is the stack of the call to the deprecated thing
Example `error.stack` output:
```
DeprecationError: my-cool-module deprecated oldfunction
at Object.<anonymous> ([eval]-wrapper:6:22)
at Module._compile (module.js:456:26)
at evalScript (node.js:532:25)
at startup (node.js:80:7)
at node.js:902:3
```
### process.env.NO_DEPRECATION
As a user of modules that are deprecated, the environment variable `NO_DEPRECATION`
is provided as a quick solution to silencing deprecation warnings from being
output. The format of this is similar to that of `DEBUG`:
```sh
$ NO_DEPRECATION=my-module,othermod node app.js
```
This will suppress deprecations from being output for "my-module" and "othermod".
The value is a list of comma-separated namespaces. To suppress every warning
across all namespaces, use the value `*` for a namespace.
**NOTE** This will not suppress the deperecations given to any "deprecation"
event listeners, just the output to STDERR.
## Display
![message](files/message.png)
When a user calls a function in your library that you mark deprecated, they
will see the following written to STDERR (in the given colors, similar colors
and layout to the `debug` module):
```
bright cyan bright yellow
| | grey cyan
| | | |
▼ ▼ ▼ ▼
my-cool-module deprecated oldfunction [eval]-wrapper:6:22
▲ ▲ ▲ ▲
| | | |
namespace | | location of mycoolmod.oldfunction() call
| deprecation message
the word "deprecated"
```
If the user redirects their STDERR to a file or somewhere that does not support
colors, they see (similar layout to the `debug` module):
```
Sun, 15 Jun 2014 05:21:37 GMT my-cool-module deprecated oldfunction at [eval]-wrapper:6:22
▲ ▲ ▲ ▲ ▲
| | | | |
timestamp of message namespace | | location of mycoolmod.oldfunction() call
| deprecation message
the word "deprecated"
```
## Examples
### Deprecating all calls to a function
This will display a deprecated message about "oldfunction" being deprecated
from "my-module" on STDERR.
```js
var deprecate = require('depd')('my-cool-module')
// message automatically derived from function name
// Object.oldfunction
exports.oldfunction = deprecate.function(function oldfunction() {
// all calls to function are deprecated
})
// specific message
exports.oldfunction = deprecate.function(function () {
// all calls to function are deprecated
}, 'oldfunction')
```
### Conditionally deprecating a function call
This will display a deprecated message about "weirdfunction" being deprecated
from "my-module" on STDERR when called with less than 2 arguments.
```js
var deprecate = require('depd')('my-cool-module')
exports.weirdfunction = function () {
if (arguments.length < 2) {
// calls with 0 or 1 args are deprecated
deprecate('weirdfunction args < 2')
}
}
```
When calling `deprecate` as a function, the warning is counted per call site
within your own module, so you can display different deprecations depending
on different situations and the users will still get all the warnings:
```js
var deprecate = require('depd')('my-cool-module')
exports.weirdfunction = function () {
if (arguments.length < 2) {
// calls with 0 or 1 args are deprecated
deprecate('weirdfunction args < 2')
} else if (typeof arguments[0] !== 'string') {
// calls with non-string first argument are deprecated
deprecate('weirdfunction non-string first arg')
}
}
```
### Deprecating property access
This will display a deprecated message about "oldprop" being deprecated
from "my-module" on STDERR when accessed. A deprecation will be displayed
when setting the value and when getting the value.
```js
var deprecate = require('depd')('my-cool-module')
exports.oldprop = 'something'
// message automatically derives from property name
deprecate.property(exports, 'oldprop')
// explicit message
deprecate.property(exports, 'oldprop', 'oldprop >= 0.10')
```
## 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.
/*!
* depd
* Copyright(c) 2014 Douglas Christopher Wilson
* MIT Licensed
*/
/**
* Module dependencies.
*/
var EventEmitter = require('events').EventEmitter
var relative = require('path').relative
/**
* Module exports.
*/
module.exports = depd
/**
* Get the path to base files on.
*/
var basePath = process.cwd()
/**
* Get listener count on event emitter.
*/
/*istanbul ignore next*/
var eventListenerCount = EventEmitter.listenerCount
|| function (emitter, type) { return emitter.listeners(type).length }
/**
* Convert a data descriptor to accessor descriptor.
*/
function convertDataDescriptorToAccessor(obj, prop, message) {
var descriptor = Object.getOwnPropertyDescriptor(obj, prop)
var value = descriptor.value
descriptor.get = function getter() { return value }
if (descriptor.writable) {
descriptor.set = function setter(val) { return value = val }
}
delete descriptor.value
delete descriptor.writable
Object.defineProperty(obj, prop, descriptor)
return descriptor
}
/**
* Create arguments string to keep arity.
*/
function createArgumentsString(arity) {
var str = ''
for (var i = 0; i < arity; i++) {
str += ', arg' + i
}
return str.substr(2)
}
/**
* Create stack string from stack.
*/
function createStackString(stack) {
var str = this.name + ': ' + this.namespace
if (this.message) {
str += ' deprecated ' + this.message
}
for (var i = 0; i < stack.length; i++) {
str += '\n at ' + stack[i].toString()
}
return str
}
/**
* Create deprecate for namespace in caller.
*/
function depd(namespace) {
if (!namespace) {
throw new TypeError('argument namespace is required')
}
var stack = getStack()
var site = callSiteLocation(stack[1])
var file = site[0]
function deprecate(message) {
// call to self as log
log.call(deprecate, message)
}
deprecate._file = file
deprecate._ignored = isignored(namespace)
deprecate._namespace = namespace
deprecate._warned = Object.create(null)
deprecate.function = wrapfunction
deprecate.property = wrapproperty
return deprecate
}
/**
* Determine if namespace is ignored.
*/
function isignored(namespace) {
var str = process.env.NO_DEPRECATION || ''
var val = str.split(/[ ,]+/)
namespace = String(namespace).toLowerCase()
for (var i = 0 ; i < val.length; i++) {
if (!(str = val[i])) continue;
// namespace ignored
if (str === '*' || str.toLowerCase() === namespace) {
return true
}
}
return false
}
/**
* Display deprecation message.
*/
function log(message, site) {
var haslisteners = eventListenerCount(process, 'deprecation') !== 0
// abort early if no destination
if (!haslisteners && this._ignored) {
return
}
var caller
var callSite
var i = 0
var seen = false
var stack = getStack()
var file = this._file
if (site) {
// provided site
callSite = callSiteLocation(stack[1])
callSite.name = site.name
file = callSite[0]
} else {
// get call site
i = 2
site = callSiteLocation(stack[i])
callSite = site
}
// get caller of deprecated thing in relation to file
for (; i < stack.length; i++) {
caller = callSiteLocation(stack[i])
if (caller[0] === file) {
seen = true
} else if (seen) {
break
}
}
var key = caller
? site.join(':') + '__' + caller.join(':')
: undefined
if (key !== undefined && key in this._warned) {
// already warned
return
}
this._warned[key] = true
// generate automatic message from call site
if (!message) {
message = callSite === site || !callSite.name
? defaultMessage(site)
: defaultMessage(callSite)
}
// emit deprecation if listeners exist
if (haslisteners) {
var err = DeprecationError(this._namespace, message, stack.slice(i))
process.emit('deprecation', err)
return
}
// format and write message
var format = process.stderr.isTTY
? formatColor
: formatPlain
var msg = format.call(this, message, caller)
process.stderr.write(msg + '\n', 'utf8')
return
}
/**
* Get call site location as array.
*/
function callSiteLocation(callSite) {
var file = callSite.getFileName() || '<anonymous>'
var line = callSite.getLineNumber()
var colm = callSite.getColumnNumber()
if (callSite.isEval()) {
file = callSite.getEvalOrigin() + ', ' + file
}
var site = [file, line, colm]
site.callSite = callSite
site.name = callSite.getFunctionName()
return site
}
/**
* Generate a default message from the site.
*/
function defaultMessage(site) {
var callSite = site.callSite
var funcName = site.name
// make useful anonymous name
if (!funcName) {
funcName = '<anonymous@' + formatLocation(site) + '>'
}
return callSite.getMethodName()
? callSite.getTypeName() + '.' + funcName
: funcName
}
/**
* Format deprecation message without color.
*/
function formatPlain(msg, caller) {
var timestamp = new Date().toUTCString()
var formatted = timestamp
+ ' ' + this._namespace
+ ' deprecated ' + msg
if (caller) {
formatted += ' at ' + formatLocation(caller)
}
return formatted
}
/**
* Format deprecation message with color.
*/
function formatColor(msg, caller) {
var formatted = '\x1b[36;1m' + this._namespace + '\x1b[22;39m' // bold cyan
+ ' \x1b[33;1mdeprecated\x1b[22;39m' // bold yellow
+ ' \x1b[90m' + msg + '\x1b[39m' // grey
if (caller) {
formatted += ' \x1b[36m' + formatLocation(caller) + '\x1b[39m' // cyan
}
return formatted
}
/**
* Format call site location.
*/
function formatLocation(callSite) {
return relative(basePath, callSite[0])
+ ':' + callSite[1]
+ ':' + callSite[2]
}
/**
* Get the stack as array of call sites.
*/
function getStack() {
var obj = {}
var prep = Error.prepareStackTrace
Error.prepareStackTrace = prepareObjectStackTrace
Error.captureStackTrace(obj, getStack)
var stack = obj.stack
Error.prepareStackTrace = prep
return stack
}
/**
* Capture call site stack from v8.
*/
function prepareObjectStackTrace(obj, stack) {
return stack
}
/**
* Return a wrapped function in a deprecation message.
*/
function wrapfunction(fn, message) {
if (typeof fn !== 'function') {
throw new TypeError('argument fn must be a function')
}
var args = createArgumentsString(fn.length)
var deprecate = this
var stack = getStack()
var site = callSiteLocation(stack[1])
site.name = fn.name
var deprecatedfn = eval('(function (' + args + ') {\n'
+ 'log.call(deprecate, message, site)\n'
+ 'return fn.apply(this, arguments)\n'
+ '})')
return deprecatedfn
}
/**
* Wrap property in a deprecation message.
*/
function wrapproperty(obj, prop, message) {
if (!obj || typeof obj !== 'object') {
throw new TypeError('argument obj must be object')
}
var descriptor = Object.getOwnPropertyDescriptor(obj, prop)
if (!descriptor) {
throw new TypeError('must call property on owner object')
}
if (!descriptor.configurable) {
throw new TypeError('property must be configurable')
}
var deprecate = this
var stack = getStack()
var site = callSiteLocation(stack[1])
// set site name
site.name = prop
// convert data descriptor
if ('value' in descriptor) {
descriptor = convertDataDescriptorToAccessor(obj, prop, message)
}
var get = descriptor.get
var set = descriptor.set
// wrap getter
if (typeof get === 'function') {
descriptor.get = function getter() {
log.call(deprecate, message, site)
return get.apply(this, arguments)
}
}
// wrap setter
if (typeof set === 'function') {
descriptor.set = function setter() {
log.call(deprecate, message, site)
return set.apply(this, arguments)
}
}
Object.defineProperty(obj, prop, descriptor)
}
/**
* Create DeprecationError for deprecation
*/
function DeprecationError(namespace, message, stack) {
var error = new Error()
var stackString
Object.defineProperty(error, 'constructor', {
value: DeprecationError
})
Object.defineProperty(error, 'message', {
configurable: true,
enumerable: false,
value: message,
writable: true
})
Object.defineProperty(error, 'name', {
enumerable: false,
configurable: true,
value: 'DeprecationError',
writable: true
})
Object.defineProperty(error, 'namespace', {
configurable: true,
enumerable: false,
value: namespace,
writable: true
})
Object.defineProperty(error, 'stack', {
configurable: true,
enumerable: false,
get: function () {
if (stackString !== undefined) {
return stackString
}
// prepare stack trace
return stackString = createStackString.call(this, stack)
},
set: function setter(val) {
stackString = val
}
})
return error
}
0.0.2 / 2014-06-19
==================
* Handle invalid status codes
0.0.1 / 2014-06-05
==================
* deps: debug@1.0.2
0.0.0 / 2014-06-05
==================
* Extracted from connect/express
# finalhandler
[![NPM version](https://badge.fury.io/js/finalhandler.svg)](https://badge.fury.io/js/finalhandler)
[![Build Status](https://travis-ci.org/expressjs/finalhandler.svg?branch=master)](https://travis-ci.org/expressjs/finalhandler)
[![Coverage Status](https://img.shields.io/coveralls/expressjs/finalhandler.svg?branch=master)](https://coveralls.io/r/expressjs/finalhandler)
Node.js function to invoke as the final step to respond to HTTP request.
## Installation
```sh
$ npm install finalhandler
```
## API
```js
var finalhandler = require('finalhandler')
```
### finalhandler(req, res, [options])
Returns function to be invoked as the final step for the given `req` and `res`.
This function is to be invoked as `fn(err)`. If `err` is falsy, the handler will
write out a 404 response to the `res`. If it is truthy, an error response will
be written out to the `res`, and `res.statusCode` is set from `err.status`.
#### options.env
By default, the environment is determined by `NODE_ENV` variable, but it can be
overridden by this option.
#### options.onerror
Provide a function to be called with the `err` when it exists. Can be used for
writing errors to a central location without excessive function generation. Called
as `onerror(err, req, res)`.
## Examples
### always 404
```js
var finalhandler = require('finalhandler')
var http = require('http')
var server = http.createServer(function (req, res) {
var done = finalhandler(req, res)
done()
})
server.listen(3000)
```
### perform simple action
```js
var finalhandler = require('finalhandler')
var fs = require('fs')
var http = require('http')
var server = http.createServer(function (req, res) {
var done = finalhandler(req, res)
fs.readFile('index.html', function (err, buf) {
if (err) return done(err)
res.setHeader('Content-Type', 'text/html')
res.end(buf)
})
})
server.listen(3000)
```
### use with middleware-style functions
```js
var finalhandler = require('finalhandler')
var http = require('http')
var serveStatic = require('serve-static')
var serve = serveStatic('public')
var server = http.createServer(function (req, res) {
var done = finalhandler(req, res)
serve(req, res, done)
})
server.listen(3000)
```
### keep log of all errors
```js
var finalhandler = require('finalhandler')
var fs = require('fs')
var http = require('http')
var server = http.createServer(function (req, res) {
var done = finalhandler(req, res, {onerror: logerror})
fs.readFile('index.html', function (err, buf) {
if (err) return done(err)
res.setHeader('Content-Type', 'text/html')
res.end(buf)
})
})
server.listen(3000)
function logerror(err) {
console.error(err.stack || err.toString())
}
```
## 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.
/*!
* finalhandler
* Copyright(c) 2014 Douglas Christopher Wilson
* MIT Licensed
*/
/**
* Module dependencies.
*/
var debug = require('debug')('finalhandler')
var escapeHtml = require('escape-html')
var http = require('http')
/**
* Variables.
*/
/* istanbul ignore next */
var defer = typeof setImmediate === 'function'
? setImmediate
: function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) }
/**
* Module exports.
*/
module.exports = finalhandler
/**
* Final handler:
*
* @param {Request} req
* @param {Response} res
* @param {Object} [options]
* @return {Function}
* @api public
*/
function finalhandler(req, res, options) {
options = options || {}
// get environment
var env = options.env || process.env.NODE_ENV || 'development'
// get error callback
var onerror = options.onerror
return function (err) {
var msg
// unhandled error
if (err) {
// default status code to 500
if (!res.statusCode || res.statusCode < 400) {
res.statusCode = 500
}
// respect err.status
if (err.status) {
res.statusCode = err.status
}
// production gets a basic error message
var msg = env === 'production'
? http.STATUS_CODES[res.statusCode]
: err.stack || err.toString()
msg = escapeHtml(msg)
.replace(/\n/g, '<br>')
.replace(/ /g, ' &nbsp;') + '\n'
} else {
res.statusCode = 404
msg = 'Cannot ' + escapeHtml(req.method) + ' ' + escapeHtml(req.originalUrl || req.url) + '\n'
}
debug('default %s', res.statusCode)
// schedule onerror callback
if (err && onerror) {
defer(onerror, err, req, res)
}
// cannot actually respond
if (res._header) {
return req.socket.destroy()
}
res.setHeader('Content-Type', 'text/html; charset=utf-8')
res.setHeader('Content-Length', Buffer.byteLength(msg, 'utf8'))
if (req.method === 'HEAD') {
res.end()
return
}
res.end(msg, 'utf8')
}
}
{
"name": "finalhandler",
"description": "Node.js final http responder",
"version": "0.0.2",
"author": {
"name": "Douglas Christopher Wilson",
"email": "doug@somethingdoug.com"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/expressjs/finalhandler"
},
"dependencies": {
"debug": "1.0.2",
"escape-html": "1.0.1"
},
"devDependencies": {
"istanbul": "0.2.10",
"mocha": "~1.20.1",
"should": "~4.0.1",
"supertest": "~0.13.0"
},
"engines": {
"node": ">= 0.8.0"
},
"scripts": {
"test": "mocha --reporter dot test/",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot test/",
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec test/"
},
"readme": "# finalhandler\n\n[![NPM version](https://badge.fury.io/js/finalhandler.svg)](https://badge.fury.io/js/finalhandler)\n[![Build Status](https://travis-ci.org/expressjs/finalhandler.svg?branch=master)](https://travis-ci.org/expressjs/finalhandler)\n[![Coverage Status](https://img.shields.io/coveralls/expressjs/finalhandler.svg?branch=master)](https://coveralls.io/r/expressjs/finalhandler)\n\nNode.js function to invoke as the final step to respond to HTTP request.\n\n## Installation\n\n```sh\n$ npm install finalhandler\n```\n\n## API\n\n```js\nvar finalhandler = require('finalhandler')\n```\n\n### finalhandler(req, res, [options])\n\nReturns function to be invoked as the final step for the given `req` and `res`.\nThis function is to be invoked as `fn(err)`. If `err` is falsy, the handler will\nwrite out a 404 response to the `res`. If it is truthy, an error response will\nbe written out to the `res`, and `res.statusCode` is set from `err.status`.\n\n#### options.env\n\nBy default, the environment is determined by `NODE_ENV` variable, but it can be\noverridden by this option.\n\n#### options.onerror\n\nProvide a function to be called with the `err` when it exists. Can be used for\nwriting errors to a central location without excessive function generation. Called\nas `onerror(err, req, res)`.\n\n## Examples\n\n### always 404\n\n```js\nvar finalhandler = require('finalhandler')\nvar http = require('http')\n\nvar server = http.createServer(function (req, res) {\n var done = finalhandler(req, res)\n done()\n})\n\nserver.listen(3000)\n```\n\n### perform simple action\n\n```js\nvar finalhandler = require('finalhandler')\nvar fs = require('fs')\nvar http = require('http')\n\nvar server = http.createServer(function (req, res) {\n var done = finalhandler(req, res)\n\n fs.readFile('index.html', function (err, buf) {\n if (err) return done(err)\n res.setHeader('Content-Type', 'text/html')\n res.end(buf)\n })\n})\n\nserver.listen(3000)\n```\n\n### use with middleware-style functions\n\n```js\nvar finalhandler = require('finalhandler')\nvar http = require('http')\nvar serveStatic = require('serve-static')\n\nvar serve = serveStatic('public')\n\nvar server = http.createServer(function (req, res) {\n var done = finalhandler(req, res)\n serve(req, res, done)\n})\n\nserver.listen(3000)\n```\n\n### keep log of all errors\n\n```js\nvar finalhandler = require('finalhandler')\nvar fs = require('fs')\nvar http = require('http')\n\nvar server = http.createServer(function (req, res) {\n var done = finalhandler(req, res, {onerror: logerror})\n\n fs.readFile('index.html', function (err, buf) {\n if (err) return done(err)\n res.setHeader('Content-Type', 'text/html')\n res.end(buf)\n })\n})\n\nserver.listen(3000)\n\nfunction logerror(err) {\n console.error(err.stack || err.toString())\n}\n```\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Douglas Christopher Wilson\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n",
"readmeFilename": "README.md",
"bugs": {
"url": "https://github.com/expressjs/finalhandler/issues"
},
"_id": "finalhandler@0.0.2",
"dist": {
"shasum": "2cadf2a004eab29417cc228bbfeb9de489c7c86d"
},
"_from": "finalhandler@0.0.2",
"_resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.0.2.tgz"
}
0.2.0 / 2014-06-18
==================
* Add `typer.format()` to format media types
0.1.0 / 2014-06-17
==================
* Accept `req` as argument to `parse`
* Accept `res` as argument to `parse`
* Parse media type with extra LWS between type and first parameter
0.0.0 / 2014-06-13
==================
* Initial implementation
# serve-static # media-typer
[![NPM version](https://badge.fury.io/js/serve-static.svg)](http://badge.fury.io/js/serve-static) [![NPM version](https://badge.fury.io/js/media-typer.svg)](https://badge.fury.io/js/media-typer)
[![Build Status](https://travis-ci.org/expressjs/serve-static.svg?branch=master)](https://travis-ci.org/expressjs/serve-static) [![Build Status](https://travis-ci.org/expressjs/media-typer.svg?branch=master)](https://travis-ci.org/expressjs/media-typer)
[![Coverage Status](https://img.shields.io/coveralls/expressjs/serve-static.svg?branch=master)](https://coveralls.io/r/expressjs/serve-static) [![Coverage Status](https://img.shields.io/coveralls/expressjs/media-typer.svg?branch=master)](https://coveralls.io/r/expressjs/media-typer)
Previously `connect.static()`. Simple RFC 6838 media type parser
## Install ## Installation
```sh ```sh
$ npm install serve-static $ npm install media-typer
``` ```
## API ## API
```js ```js
var serveStatic = require('serve-static') var typer = require('media-typer')
``` ```
### serveStatic(root, options) ### typer.parse(string)
Create a new middleware function to serve files from within a given root ```js
directory. The file to serve will be determined by combining `req.url` var obj = typer.parse('image/svg+xml; charset=utf-8')
with the provided root directory. ```
Options: Parse a media type string. This will return an object with the following
properties (examples are shown for the string `'image/svg+xml; charset=utf-8'`):
- `hidden` Allow transfer of hidden files. defaults to `false` - `type`: The type of the media type (always lower case). Example: `'image'`
- `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 - `subtype`: The subtype of the media type (always lower case). Example: `'svg'`
### Serve files with vanilla node.js http server - `suffix`: The suffix of the media type (always lower case). Example: `'xml'`
```js - `parameters`: An object of the parameters in the media type (name of parameter always lower case). Example: `{charset: 'utf-8'}`
var finalhandler = require('finalhandler')
var http = require('http')
var serveStatic = require('serve-static')
// Serve up public/ftp folder ### typer.parse(req)
var serve = serveStatic('public/ftp', {'index': ['index.html', 'index.htm']})
// Create server ```js
var server = http.createServer(function(req, res){ var obj = typer.parse(req)
var done = finalhandler(req, res)
serve(req, res, done)
})
// Listen
server.listen(3000)
``` ```
### Serve all files from ftp folder Parse the `content-type` header from the given `req`. Short-cut for
`typer.parse(req.headers['content-type'])`.
### typer.parse(res)
```js ```js
var connect = require('connect') var obj = typer.parse(req)
var serveStatic = require('serve-static') ```
Parse the `content-type` header set on the given `res`. Short-cut for
`typer.parse(res.getHeader('content-type'))`.
var app = connect() ### typer.format(obj)
app.use(serveStatic('public/ftp', {'index': ['default.html', 'default.htm']})) ```js
app.listen(3000) var obj = typer.format({type: 'image', subtype: 'svg', suffix: 'xml'})
``` ```
Format an object into a media type string. This will return a string of the
mime type for the given object. For the properties of the object, see the
documentation for `typer.parse(string)`.
## License ## License
The MIT License (MIT) The MIT License (MIT)
......
/*!
* media-typer
* Copyright(c) 2014 Douglas Christopher Wilson
* MIT Licensed
*/
/**
* RegExp to match *( ";" parameter ) in RFC 2616 sec 3.7
*
* parameter = token "=" ( token | quoted-string )
* token = 1*<any CHAR except CTLs or separators>
* separators = "(" | ")" | "<" | ">" | "@"
* | "," | ";" | ":" | "\" | <">
* | "/" | "[" | "]" | "?" | "="
* | "{" | "}" | SP | HT
* quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
* qdtext = <any TEXT except <">>
* quoted-pair = "\" CHAR
* CHAR = <any US-ASCII character (octets 0 - 127)>
* TEXT = <any OCTET except CTLs, but including LWS>
* LWS = [CRLF] 1*( SP | HT )
* CRLF = CR LF
* CR = <US-ASCII CR, carriage return (13)>
* LF = <US-ASCII LF, linefeed (10)>
* SP = <US-ASCII SP, space (32)>
* SHT = <US-ASCII HT, horizontal-tab (9)>
* CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
* OCTET = <any 8-bit sequence of data>
*/
var paramRegExp = /; *([!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+) *= *("(?:[ !\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u0020-\u007e])*"|[!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+) */g;
var textRegExp = /^[\u0020-\u007e\u0080-\u00ff]+$/
var tokenRegExp = /^[!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+$/
/**
* RegExp to match quoted-pair in RFC 2616
*
* quoted-pair = "\" CHAR
* CHAR = <any US-ASCII character (octets 0 - 127)>
*/
var qescRegExp = /\\([\u0000-\u007f])/g;
/**
* RegExp to match chars that must be quoted-pair in RFC 2616
*/
var quoteRegExp = /([\\"])/g;
/**
* RegExp to match type in RFC 6838
*
* type-name = restricted-name
* subtype-name = restricted-name
* restricted-name = restricted-name-first *126restricted-name-chars
* restricted-name-first = ALPHA / DIGIT
* restricted-name-chars = ALPHA / DIGIT / "!" / "#" /
* "$" / "&" / "-" / "^" / "_"
* restricted-name-chars =/ "." ; Characters before first dot always
* ; specify a facet name
* restricted-name-chars =/ "+" ; Characters after last plus always
* ; specify a structured syntax suffix
* ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
* DIGIT = %x30-39 ; 0-9
*/
var subtypeNameRegExp = /^[A-Za-z0-9][A-Za-z0-9!#$&^_.-]{0,126}$/
var typeNameRegExp = /^[A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126}$/
var typeRegExp = /^ *([A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126})\/([A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}) *$/;
/**
* Module exports.
*/
exports.format = format
exports.parse = parse
/**
* Format object to media type.
*
* @param {object} obj
* @return {string}
* @api public
*/
function format(obj) {
if (!obj || typeof obj !== 'object') {
throw new TypeError('argument obj is required')
}
var parameters = obj.parameters
var subtype = obj.subtype
var suffix = obj.suffix
var type = obj.type
if (!type || !typeNameRegExp.test(type)) {
throw new TypeError('invalid type')
}
if (!subtype || !subtypeNameRegExp.test(subtype)) {
throw new TypeError('invalid subtype')
}
// format as type/subtype
var string = type + '/' + subtype
// append +suffix
if (suffix) {
if (!typeNameRegExp.test(suffix)) {
throw new TypeError('invalid suffix')
}
string += '+' + suffix
}
// append parameters
if (parameters && typeof parameters === 'object') {
var param
var params = Object.keys(parameters).sort()
for (var i = 0; i < params.length; i++) {
param = params[i]
if (!tokenRegExp.test(param)) {
throw new TypeError('invalid parameter name')
}
string += '; ' + param + '=' + qstring(parameters[param])
}
}
return string
}
/**
* Parse media type to object.
*
* @param {string|object} string
* @return {Object}
* @api public
*/
function parse(string) {
if (!string) {
throw new TypeError('argument string is required')
}
// support req/res-like objects as argument
if (typeof string === 'object') {
string = getcontenttype(string)
}
if (typeof string !== 'string') {
throw new TypeError('argument string is required to be a string')
}
var index = string.indexOf(';')
var type = index !== -1
? string.substr(0, index)
: string
var key
var match
var obj = splitType(type)
var params = {}
var value
paramRegExp.lastIndex = index
while (match = paramRegExp.exec(string)) {
key = match[1].toLowerCase()
value = match[2]
if (value[0] === '"') {
// remove quotes and escapes
value = value
.substr(1, value.length - 2)
.replace(qescRegExp, '$1')
}
params[key] = value
}
obj.parameters = params
return obj
}
/**
* Get content-type from req/res objects.
*
* @param {object}
* @return {Object}
* @api private
*/
function getcontenttype(obj) {
if (typeof obj.getHeader === 'function') {
// res-like
return obj.getHeader('content-type')
}
if (typeof obj.headers === 'object') {
// req-like
return obj.headers && obj.headers['content-type']
}
}
/**
* Quote a string if necessary.
*
* @param {string} val
* @return {string}
* @api private
*/
function qstring(val) {
var str = String(val)
// no need to quote tokens
if (tokenRegExp.test(str)) {
return str
}
if (str.length > 0 && !textRegExp.test(str)) {
throw new TypeError('invalid parameter value')
}
return '"' + str.replace(quoteRegExp, '\\$1') + '"'
}
/**
* Simply "type/subtype+siffx" into parts.
*
* @param {string} string
* @return {Object}
* @api private
*/
function splitType(string) {
var match = typeRegExp.exec(string.toLowerCase())
if (!match) {
throw new TypeError('invalid media type')
}
var type = match[1]
var subtype = match[2]
var suffix
// suffix after last +
var index = subtype.lastIndexOf('+')
if (index !== -1) {
suffix = subtype.substr(index + 1)
subtype = subtype.substr(0, index)
}
var obj = {
type: type,
subtype: subtype,
suffix: suffix
}
return obj
}
{
"name": "media-typer",
"description": "Simple RFC 6838 media type parser and formatter",
"version": "0.2.0",
"author": {
"name": "Douglas Christopher Wilson",
"email": "doug@somethingdoug.com"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/expressjs/media-typer"
},
"devDependencies": {
"istanbul": "0.2.10",
"mocha": "~1.20.1",
"should": "~4.0.4"
},
"engines": {
"node": ">= 0.8.0"
},
"scripts": {
"test": "mocha --reporter dot test/",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot test/",
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec test/"
},
"readme": "# media-typer\n\n[![NPM version](https://badge.fury.io/js/media-typer.svg)](https://badge.fury.io/js/media-typer)\n[![Build Status](https://travis-ci.org/expressjs/media-typer.svg?branch=master)](https://travis-ci.org/expressjs/media-typer)\n[![Coverage Status](https://img.shields.io/coveralls/expressjs/media-typer.svg?branch=master)](https://coveralls.io/r/expressjs/media-typer)\n\nSimple RFC 6838 media type parser\n\n## Installation\n\n```sh\n$ npm install media-typer\n```\n\n## API\n\n```js\nvar typer = require('media-typer')\n```\n\n### typer.parse(string)\n\n```js\nvar obj = typer.parse('image/svg+xml; charset=utf-8')\n```\n\nParse a media type string. This will return an object with the following\nproperties (examples are shown for the string `'image/svg+xml; charset=utf-8'`):\n\n - `type`: The type of the media type (always lower case). Example: `'image'`\n\n - `subtype`: The subtype of the media type (always lower case). Example: `'svg'`\n\n - `suffix`: The suffix of the media type (always lower case). Example: `'xml'`\n\n - `parameters`: An object of the parameters in the media type (name of parameter always lower case). Example: `{charset: 'utf-8'}`\n\n### typer.parse(req)\n\n```js\nvar obj = typer.parse(req)\n```\n\nParse the `content-type` header from the given `req`. Short-cut for\n`typer.parse(req.headers['content-type'])`.\n\n### typer.parse(res)\n\n```js\nvar obj = typer.parse(req)\n```\n\nParse the `content-type` header set on the given `res`. Short-cut for\n`typer.parse(res.getHeader('content-type'))`.\n\n### typer.format(obj)\n\n```js\nvar obj = typer.format({type: 'image', subtype: 'svg', suffix: 'xml'})\n```\n\nFormat an object into a media type string. This will return a string of the\nmime type for the given object. For the properties of the object, see the\ndocumentation for `typer.parse(string)`.\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Douglas Christopher Wilson\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n",
"readmeFilename": "README.md",
"bugs": {
"url": "https://github.com/expressjs/media-typer/issues"
},
"_id": "media-typer@0.2.0",
"dist": {
"shasum": "2af3fe9842d954b5a16d102d197d8a47ead20d3a"
},
"_from": "media-typer@0.2.0",
"_resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.2.0.tgz"
}
...@@ -19,5 +19,6 @@ ...@@ -19,5 +19,6 @@
"readme": "# parseurl\n\nParse a URL with memoization.\n\n## API\n\n### var pathname = parseurl(req)\n\n`pathname` can then be passed to a router or something.\n\n## LICENSE\n\n(The MIT License)\n\nCopyright (c) 2014 Jonathan Ong <me@jongleberry.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", "readme": "# parseurl\n\nParse a URL with memoization.\n\n## API\n\n### var pathname = parseurl(req)\n\n`pathname` can then be passed to a router or something.\n\n## LICENSE\n\n(The MIT License)\n\nCopyright (c) 2014 Jonathan Ong <me@jongleberry.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
"readmeFilename": "README.md", "readmeFilename": "README.md",
"_id": "parseurl@1.0.1", "_id": "parseurl@1.0.1",
"_from": "parseurl@1.0.1" "_from": "parseurl@1.0.1",
"scripts": {}
} }
...@@ -33,9 +33,5 @@ ...@@ -33,9 +33,5 @@
"url": "https://github.com/visionmedia/node-querystring/issues" "url": "https://github.com/visionmedia/node-querystring/issues"
}, },
"_id": "qs@0.6.6", "_id": "qs@0.6.6",
"dist": { "_from": "qs@0.6.6"
"shasum": "8d67e3069ef48c8e2bd2a80aa82c69db08996713"
},
"_from": "qs@0.6.6",
"_resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz"
} }
0.5.0 / 2014-06-28
==================
* Accept string for `maxAge` (converted by `ms`)
* Add `headers` event
* Include link in default redirect response
* Use `EventEmitter.listenerCount` to count listeners
0.4.3 / 2014-06-11 0.4.3 / 2014-06-11
================== ==================
......
...@@ -38,6 +38,12 @@ var app = http.createServer(function(req, res){ ...@@ -38,6 +38,12 @@ var app = http.createServer(function(req, res){
res.end(err.message); res.end(err.message);
} }
// your custom headers
function headers(res, path, stat) {
// serve all files for download
res.setHeader('Content-Disposition', 'attachment');
}
// your custom directory handling logic: // your custom directory handling logic:
function redirect() { function redirect() {
res.statusCode = 301; res.statusCode = 301;
...@@ -50,6 +56,7 @@ var app = http.createServer(function(req, res){ ...@@ -50,6 +56,7 @@ var app = http.createServer(function(req, res){
send(req, url.parse(req.url).pathname, {root: '/www/example.com/public'}) send(req, url.parse(req.url).pathname, {root: '/www/example.com/public'})
.on('error', error) .on('error', error)
.on('directory', redirect) .on('directory', redirect)
.on('headers', headers)
.pipe(res); .pipe(res);
}).listen(3000); }).listen(3000);
``` ```
...@@ -75,6 +82,8 @@ var app = http.createServer(function(req, res){ ...@@ -75,6 +82,8 @@ var app = http.createServer(function(req, res){
#### maxage #### maxage
Provide a max-age in milliseconds for http caching, defaults to 0. 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.
#### root #### root
...@@ -85,6 +94,7 @@ var app = http.createServer(function(req, res){ ...@@ -85,6 +94,7 @@ var app = http.createServer(function(req, res){
- `error` an error occurred `(err)` - `error` an error occurred `(err)`
- `directory` a directory was requested - `directory` a directory was requested
- `file` a file was requested `(path, stat)` - `file` a file was requested `(path, stat)`
- `headers` the headers are about to be set on a file `(res, path, stat)`
- `stream` file streaming has started `(stream)` - `stream` file streaming has started `(stream)`
- `end` streaming has completed - `end` streaming has completed
...@@ -105,6 +115,8 @@ var app = http.createServer(function(req, res){ ...@@ -105,6 +115,8 @@ var app = http.createServer(function(req, res){
### .maxage(ms) ### .maxage(ms)
Provide a max-age in milliseconds for http caching, defaults to 0. 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.
### .hidden(bool) ### .hidden(bool)
......
...@@ -17,6 +17,8 @@ var escapeHtml = require('escape-html') ...@@ -17,6 +17,8 @@ var escapeHtml = require('escape-html')
, normalize = path.normalize , normalize = path.normalize
, join = path.join , join = path.join
, utils = require('./utils'); , utils = require('./utils');
var EventEmitter = require('events').EventEmitter;
var ms = require('ms');
var upPathRegexp = /(?:^|[\\\/])\.\.(?:[\\\/]|$)/; var upPathRegexp = /(?:^|[\\\/])\.\.(?:[\\\/]|$)/;
...@@ -32,6 +34,14 @@ exports = module.exports = send; ...@@ -32,6 +34,14 @@ exports = module.exports = send;
exports.mime = mime; exports.mime = mime;
/**
* Shim EventEmitter.listenerCount for node.js < 0.10
*/
/* istanbul ignore next */
var listenerCount = EventEmitter.listenerCount
|| function(emitter, type){ return emitter.listeners(type).length; };
/** /**
* Return a `SendStream` for `req` and `path`. * Return a `SendStream` for `req` and `path`.
* *
...@@ -143,19 +153,21 @@ SendStream.prototype.from = function(path){ ...@@ -143,19 +153,21 @@ SendStream.prototype.from = function(path){
}; };
/** /**
* Set max-age to `ms`. * Set max-age to `maxAge`.
* *
* @param {Number} ms * @param {Number} maxAge
* @return {SendStream} * @return {SendStream}
* @api public * @api public
*/ */
SendStream.prototype.maxage = function(ms){ SendStream.prototype.maxage = function maxage(maxAge){
ms = Number(ms); maxAge = typeof maxAge === 'string'
if (isNaN(ms)) ms = 0; ? ms(maxAge)
if (Infinity == ms) ms = 60 * 60 * 24 * 365 * 1000; : Number(maxAge);
debug('max-age %d', ms); if (isNaN(maxAge)) maxAge = 0;
this._maxage = ms; if (Infinity == maxAge) maxAge = 60 * 60 * 24 * 365 * 1000;
debug('max-age %d', maxAge);
this._maxage = maxAge;
return this; return this;
}; };
...@@ -174,7 +186,7 @@ SendStream.prototype.error = function(status, err){ ...@@ -174,7 +186,7 @@ SendStream.prototype.error = function(status, err){
err.status = status; err.status = status;
// emit if listeners instead of responding // emit if listeners instead of responding
if (this.listeners('error').length) { if (listenerCount(this, 'error') !== 0) {
return this.emit('error', err); return this.emit('error', err);
} }
...@@ -333,13 +345,17 @@ SendStream.prototype.isRangeFresh = function isRangeFresh(){ ...@@ -333,13 +345,17 @@ SendStream.prototype.isRangeFresh = function isRangeFresh(){
*/ */
SendStream.prototype.redirect = function(path){ SendStream.prototype.redirect = function(path){
if (this.listeners('directory').length) return this.emit('directory'); if (listenerCount(this, 'directory') !== 0) {
return this.emit('directory');
}
if (this.hasTrailingSlash()) return this.error(403); if (this.hasTrailingSlash()) return this.error(403);
var res = this.res; var res = this.res;
path += '/'; path += '/';
res.statusCode = 301; res.statusCode = 301;
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.setHeader('Location', path); res.setHeader('Location', path);
res.end('Redirecting to ' + escapeHtml(path)); res.end('Redirecting to <a href="' + escapeHtml(path) + '">' + escapeHtml(path) + '</a>\n');
}; };
/** /**
...@@ -592,6 +608,9 @@ SendStream.prototype.type = function(path){ ...@@ -592,6 +608,9 @@ SendStream.prototype.type = function(path){
SendStream.prototype.setHeader = function setHeader(path, stat){ SendStream.prototype.setHeader = function setHeader(path, stat){
var res = this.res; var res = this.res;
this.emit('headers', res, path, stat);
if (!res.getHeader('Accept-Ranges')) res.setHeader('Accept-Ranges', 'bytes'); if (!res.getHeader('Accept-Ranges')) res.setHeader('Accept-Ranges', 'bytes');
if (!res.getHeader('Date')) res.setHeader('Date', new Date().toUTCString()); if (!res.getHeader('Date')) res.setHeader('Date', new Date().toUTCString());
if (!res.getHeader('Cache-Control')) res.setHeader('Cache-Control', 'public, max-age=' + Math.floor(this._maxage / 1000)); if (!res.getHeader('Cache-Control')) res.setHeader('Cache-Control', 'public, max-age=' + Math.floor(this._maxage / 1000));
......
# ms.js: miliseconds conversion utility
```js
ms('1d') // 86400000
ms('10h') // 36000000
ms('2h') // 7200000
ms('1m') // 60000
ms('5s') // 5000
ms('100') // 100
```
```js
ms(60000) // "1m"
ms(2 * 60000) // "2m"
ms(ms('10 hours')) // "10h"
```
```js
ms(60000, { long: true }) // "1 minute"
ms(2 * 60000, { long: true }) // "2 minutes"
ms(ms('10 hours', { long: true })) // "10 hours"
```
- Node/Browser compatible. Published as `ms` in NPM.
- If a number is supplied to `ms`, a string with a unit is returned.
- If a string that contains the number is supplied, it returns it as
a number (e.g: it returns `100` for `'100'`).
- If you pass a string with a number and a valid unit, the number of
equivalent ms is returned.
## License
MIT
\ No newline at end of file
/**
* Helpers.
*/
var s = 1000;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var y = d * 365.25;
/**
* Parse or format the given `val`.
*
* Options:
*
* - `long` verbose formatting [false]
*
* @param {String|Number} val
* @param {Object} options
* @return {String|Number}
* @api public
*/
module.exports = function(val, options){
options = options || {};
if ('string' == typeof val) return parse(val);
return options.long
? long(val)
: short(val);
};
/**
* Parse the given `str` and return milliseconds.
*
* @param {String} str
* @return {Number}
* @api private
*/
function parse(str) {
var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
if (!match) return;
var n = parseFloat(match[1]);
var type = (match[2] || 'ms').toLowerCase();
switch (type) {
case 'years':
case 'year':
case 'y':
return n * y;
case 'days':
case 'day':
case 'd':
return n * d;
case 'hours':
case 'hour':
case 'h':
return n * h;
case 'minutes':
case 'minute':
case 'm':
return n * m;
case 'seconds':
case 'second':
case 's':
return n * s;
case 'ms':
return n;
}
}
/**
* Short format for `ms`.
*
* @param {Number} ms
* @return {String}
* @api private
*/
function short(ms) {
if (ms >= d) return Math.round(ms / d) + 'd';
if (ms >= h) return Math.round(ms / h) + 'h';
if (ms >= m) return Math.round(ms / m) + 'm';
if (ms >= s) return Math.round(ms / s) + 's';
return ms + 'ms';
}
/**
* Long format for `ms`.
*
* @param {Number} ms
* @return {String}
* @api private
*/
function long(ms) {
return plural(ms, d, 'day')
|| plural(ms, h, 'hour')
|| plural(ms, m, 'minute')
|| plural(ms, s, 'second')
|| ms + ' ms';
}
/**
* Pluralization helper.
*/
function plural(ms, n, name) {
if (ms < n) return;
if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
return Math.ceil(ms / n) + ' ' + name + 's';
}
{
"name": "ms",
"version": "0.6.2",
"description": "Tiny ms conversion utility",
"repository": {
"type": "git",
"url": "git://github.com/guille/ms.js.git"
},
"main": "./index",
"devDependencies": {
"mocha": "*",
"expect.js": "*",
"serve": "*"
},
"component": {
"scripts": {
"ms/index.js": "index.js"
}
},
"readme": "# ms.js: miliseconds conversion utility\n\n```js\nms('1d') // 86400000\nms('10h') // 36000000\nms('2h') // 7200000\nms('1m') // 60000\nms('5s') // 5000\nms('100') // 100\n```\n\n```js\nms(60000) // \"1m\"\nms(2 * 60000) // \"2m\"\nms(ms('10 hours')) // \"10h\"\n```\n\n```js\nms(60000, { long: true }) // \"1 minute\"\nms(2 * 60000, { long: true }) // \"2 minutes\"\nms(ms('10 hours', { long: true })) // \"10 hours\"\n```\n\n- Node/Browser compatible. Published as `ms` in NPM.\n- If a number is supplied to `ms`, a string with a unit is returned.\n- If a string that contains the number is supplied, it returns it as\na number (e.g: it returns `100` for `'100'`).\n- If you pass a string with a number and a valid unit, the number of\nequivalent ms is returned.\n\n## License\n\nMIT",
"readmeFilename": "README.md",
"bugs": {
"url": "https://github.com/guille/ms.js/issues"
},
"_id": "ms@0.6.2",
"dist": {
"shasum": "f13296ecf600d296c9f2ff2b61f2f9eb12a69c79"
},
"_from": "ms@0.6.2",
"_resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz",
"scripts": {}
}
1.2.3 / 2014-06-11
==================
* deps: send@0.4.3
- Do not throw un-catchable error on file open race condition
- Use `escape-html` for HTML escaping
- deps: debug@1.0.2
- deps: finished@1.2.2
- deps: fresh@0.2.2
1.2.2 / 2014-06-09
==================
* deps: send@0.4.2
- fix "event emitter leak" warnings
- deps: debug@1.0.1
- deps: finished@1.2.1
1.2.1 / 2014-06-02
==================
* use `escape-html` for escaping
* deps: send@0.4.1
- Send `max-age` in `Cache-Control` in correct format
1.2.0 / 2014-05-29
==================
* deps: send@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@0.8.1
1.1.0 / 2014-04-24
==================
* Accept options directly to `send` module
* deps: send@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@0.2.0
1.0.1 / 2014-03-05
==================
* Add mime export for back-compat
1.0.0 / 2014-03-05
==================
* Genesis from `connect`
/*!
* serve-static
* Copyright(c) 2010 Sencha Inc.
* Copyright(c) 2011 TJ Holowaychuk
* Copyright(c) 2014 Douglas Christopher Wilson
* MIT Licensed
*/
/**
* Module dependencies.
*/
var escapeHtml = require('escape-html');
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 ' + escapeHtml(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;
/**
* 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;
};
{
"name": "serve-static",
"description": "Serve static files",
"version": "1.2.3",
"author": {
"name": "Douglas Christopher Wilson",
"email": "doug@somethingdoug.com"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/expressjs/serve-static"
},
"dependencies": {
"escape-html": "1.0.1",
"parseurl": "1.0.1",
"send": "0.4.3"
},
"devDependencies": {
"istanbul": "0.2.10",
"mocha": "~1.20.0",
"should": "~4.0.0",
"supertest": "~0.13.0"
},
"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/"
},
"readme": "# serve-static\n\n[![NPM version](https://badge.fury.io/js/serve-static.svg)](http://badge.fury.io/js/serve-static)\n[![Build Status](https://travis-ci.org/expressjs/serve-static.svg?branch=master)](https://travis-ci.org/expressjs/serve-static)\n[![Coverage Status](https://img.shields.io/coveralls/expressjs/serve-static.svg?branch=master)](https://coveralls.io/r/expressjs/serve-static)\n\nPreviously `connect.static()`.\n\n## Install\n\n```sh\n$ npm install serve-static\n```\n\n## API\n\n```js\nvar serveStatic = require('serve-static')\n```\n\n### serveStatic(root, options)\n\nCreate a new middleware function to serve files from within a given root\ndirectory. The file to serve will be determined by combining `req.url`\nwith the provided root directory.\n\nOptions:\n\n- `hidden` Allow transfer of hidden files. defaults to `false`\n- `index` Default file name, defaults to `'index.html'`\n- `maxAge` Browser cache maxAge in milliseconds. defaults to `0`\n- `redirect` Redirect to trailing \"/\" when the pathname is a dir. defaults to `true`\n\n## Examples\n\n### Serve files with vanilla node.js http server\n\n```js\nvar finalhandler = require('finalhandler')\nvar http = require('http')\nvar serveStatic = require('serve-static')\n\n// Serve up public/ftp folder\nvar serve = serveStatic('public/ftp', {'index': ['index.html', 'index.htm']})\n\n// Create server\nvar server = http.createServer(function(req, res){\n var done = finalhandler(req, res)\n serve(req, res, done)\n})\n\n// Listen\nserver.listen(3000)\n```\n\n### Serve all files from ftp folder\n\n```js\nvar connect = require('connect')\nvar serveStatic = require('serve-static')\n\nvar app = connect()\n\napp.use(serveStatic('public/ftp', {'index': ['default.html', 'default.htm']}))\napp.listen(3000)\n```\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Douglas Christopher Wilson\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n",
"readmeFilename": "Readme.md",
"bugs": {
"url": "https://github.com/expressjs/serve-static/issues"
},
"_id": "serve-static@1.2.3",
"dist": {
"shasum": "0d8f17dfa35aff543e12cb9ee964da30e415ede9"
},
"_from": "serve-static@1.2.3",
"_resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.2.3.tgz"
}
1.3.2 / 2014-06-24
==================
* use `~` range on mime-types
1.3.1 / 2014-06-19
==================
* fix global variable leak
1.3.0 / 2014-06-19
==================
* improve type parsing
- invalid media type never matches
- media type not case-sensitive
- extra LWS does not affect results
1.2.2 / 2014-06-19
==================
* fix behavior on unknown type argument
1.2.1 / 2014-06-03 1.2.1 / 2014-06-03
================== ==================
* Switch dependency from `mime` to `mime-types@1.0.0` * switch dependency from `mime` to `mime-types@1.0.0`
1.2.0 / 2014-05-11 1.2.0 / 2014-05-11
================== ==================
......
# type-is [![Build Status](https://travis-ci.org/expressjs/type-is.svg?branch=master)](https://travis-ci.org/expressjs/type-is) [![NPM version](https://badge.fury.io/js/type-is.svg)](https://badge.fury.io/js/type-is) # type-is
[![NPM version](https://badge.fury.io/js/type-is.svg)](https://badge.fury.io/js/type-is)
[![Build Status](https://travis-ci.org/expressjs/type-is.svg?branch=master)](https://travis-ci.org/expressjs/type-is)
[![Coverage Status](https://img.shields.io/coveralls/expressjs/type-is.svg?branch=master)](https://coveralls.io/r/expressjs/type-is)
Infer the content-type of a request. Infer the content-type of a request.
...@@ -15,7 +19,8 @@ var http = require('http') ...@@ -15,7 +19,8 @@ var http = require('http')
var is = require('type-is') var is = require('type-is')
http.createServer(function (req, res) { http.createServer(function (req, res) {
is(req, ['text/*']) var istext = is(req, ['text/*'])
res.end('you ' + (istext ? 'sent' : 'did not send') + ' me text')
}) })
``` ```
...@@ -53,9 +58,7 @@ var parse = require('body'); ...@@ -53,9 +58,7 @@ var parse = require('body');
var busboy = require('busboy'); var busboy = require('busboy');
function bodyParser(req, res, next) { function bodyParser(req, res, next) {
var hasRequestBody = 'content-type' in req.headers if (!is.hasBody(req)) return next();
|| 'transfer-encoding' in req.headers;
if (!hasRequestBody) return next();
switch (is(req, ['urlencoded', 'json', 'multipart'])) { switch (is(req, ['urlencoded', 'json', 'multipart'])) {
case 'urlencoded': case 'urlencoded':
......
var mime = require('mime-types'); var typer = require('media-typer')
var mime = require('mime-types')
var slice = [].slice;
module.exports = typeofrequest; module.exports = typeofrequest;
typeofrequest.is = typeis; typeofrequest.is = typeis;
...@@ -23,19 +22,31 @@ typeofrequest.match = mimeMatch; ...@@ -23,19 +22,31 @@ typeofrequest.match = mimeMatch;
* @return String * @return String
*/ */
function typeis(value, types) { function typeis(value, types_) {
if (!value) return false; var i
if (types && !Array.isArray(types)) types = slice.call(arguments, 1); var types = types_
// remove parameters and normalize
value = typenormalize(value)
// no type or invalid
if (!value) {
return false
}
// remove stuff like charsets // support flattened arguments
var index = value.indexOf(';') if (types && !Array.isArray(types)) {
value = ~index ? value.slice(0, index) : value types = new Array(arguments.length - 1)
for (i = 0; i < types.length; i++) {
types[i] = arguments[i + 1]
}
}
// no types, return the content type // no types, return the content type
if (!types || !types.length) return value; if (!types || !types.length) return value;
var type; var type
for (var i = 0; i < types.length; i++) { for (i = 0; i < types.length; i++) {
if (mimeMatch(normalize(type = types[i]), value)) { if (mimeMatch(normalize(type = types[i]), value)) {
return type[0] === '+' || ~type.indexOf('*') return type[0] === '+' || ~type.indexOf('*')
? value ? value
...@@ -94,10 +105,26 @@ function hasbody(req) { ...@@ -94,10 +105,26 @@ function hasbody(req) {
* @api public * @api public
*/ */
function typeofrequest(req, types) { function typeofrequest(req, types_) {
if (!hasbody(req)) return null; var types = types_
if (types && !Array.isArray(types)) types = slice.call(arguments, 1);
return typeis(req.headers['content-type'], types); // no body
if (!hasbody(req)) {
return null
}
// support flattened arguments
if (arguments.length > 2) {
types = new Array(arguments.length - 1)
for (var i = 0; i < types.length; i++) {
types[i] = arguments[i + 1]
}
}
// request content type
var value = req.headers['content-type']
return typeis(value, types);
} }
/** /**
...@@ -141,7 +168,15 @@ function normalize(type) { ...@@ -141,7 +168,15 @@ function normalize(type) {
*/ */
function mimeMatch(expected, actual) { function mimeMatch(expected, actual) {
if (expected === actual) return true; // invalid type
if (expected === false) {
return false
}
// exact match
if (expected === actual) {
return true
}
actual = actual.split('/'); actual = actual.split('/');
...@@ -175,3 +210,21 @@ function mimeMatch(expected, actual) { ...@@ -175,3 +210,21 @@ function mimeMatch(expected, actual) {
return false return false
} }
/**
* Normalize a type and remove parameters.
*
* @param {string} value
* @return {string}
* @api private
*/
function typenormalize(value) {
try {
var type = typer.parse(value)
delete type.parameters
return typer.format(type)
} catch (err) {
return null
}
}
# Compiled source # test
################### build.js
*.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 # # OS generated files #
###################### ######################
...@@ -35,18 +10,5 @@ Thumbs.db ...@@ -35,18 +10,5 @@ Thumbs.db
# Node.js # # Node.js #
########### ###########
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz
pids
logs
results
node_modules node_modules
npm-debug.log npm-debug.log
language: node_js language: node_js
node_js: node_js:
- "0.8"
- "0.10" - "0.10"
- "0.11"
matrix:
allow_failures:
- node_js: "0.11"
fast_finish: true
before_install:
# remove build script deps before install
- node -pe 'f="./package.json";p=require(f);d=p.devDependencies;for(k in d){if("co"===k.substr(0,2))delete d[k]}require("fs").writeFileSync(f,JSON.stringify(p,null,2))'
# mime-types [![Build Status](https://travis-ci.org/expressjs/mime-types.svg?branch=master)](https://travis-ci.org/expressjs/mime-types) [![NPM version](https://badge.fury.io/js/mime-types.svg)](https://badge.fury.io/js/mime-types) # mime-types
[![NPM version](https://badge.fury.io/js/mime-types.svg)](https://badge.fury.io/js/mime-types) [![Build Status](https://travis-ci.org/expressjs/mime-types.svg?branch=master)](https://travis-ci.org/expressjs/mime-types)
The ultimate javascript content-type utility. The ultimate javascript content-type utility.
...@@ -8,10 +9,10 @@ The ultimate javascript content-type utility. ...@@ -8,10 +9,10 @@ The ultimate javascript content-type utility.
$ npm install mime-types $ npm install mime-types
``` ```
#### Similar to [mime](https://github.com/broofa/node-mime) except: #### Similar to [node-mime](https://github.com/broofa/node-mime), except:
- __No fallbacks.__ Instead of naively returning the first available type, `mime-types` simply returns `false`, so do `var type = mime.lookup('unrecognized') || 'application/octet-stream'`.
- No `new Mime()` business, so you could do `var lookup = require('mime-types').lookup`. - No `new Mime()` business, so you could do `var lookup = require('mime-types').lookup`.
- No fallbacks, so do `var type = mime.lookup('unrecognized') || 'application/octet-stream'`.
- Additional mime types are added such as jade and stylus. Feel free to add more! - Additional mime types are added such as jade and stylus. Feel free to add more!
- Browser support via Browserify and Component by converting lists to JSON files. - Browser support via Browserify and Component by converting lists to JSON files.
......
...@@ -8,6 +8,7 @@ even if it's from an unofficial source. ...@@ -8,6 +8,7 @@ even if it's from an unofficial source.
- `text/coffeescript` - http://coffeescript.org/#scripts - `text/coffeescript` - http://coffeescript.org/#scripts
- `text/x-handlebars-template` - https://handlebarsjs.com/#getting-started - `text/x-handlebars-template` - https://handlebarsjs.com/#getting-started
- `text/x-sass` & `text/x-scss` - https://github.com/janlelis/rubybuntu-mime/blob/master/sass.xml - `text/x-sass` & `text/x-scss` - https://github.com/janlelis/rubybuntu-mime/blob/master/sass.xml
- `text.jsx` - http://facebook.github.io/react/docs/getting-started.html [[2]](https://github.com/facebook/react/blob/f230e0a03154e6f8a616e0da1fb3d97ffa1a6472/vendor/browser-transforms.js#L210)
[Sources for node.json types](https://github.com/broofa/node-mime/blob/master/types/node.types) [Sources for node.json types](https://github.com/broofa/node-mime/blob/master/types/node.types)
......
/**
* http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
* https://github.com/broofa/node-mime/blob/master/types/node.types
*
* Convert these text files to JSON for browser usage.
*/
var co = require('co')
var fs = require('fs')
var path = require('path')
var cogent = require('cogent')
function* get(url) {
var res = yield* cogent(url, {
string: true
})
if (res.statusCode !== 200)
throw new Error('got status code ' + res.statusCode + ' from ' + url)
var text = res.text
var json = {}
// http://en.wikipedia.org/wiki/Internet_media_type#Naming
/**
* Mime types and associated extensions are stored in the form:
*
* <type> <ext> <ext> <ext>
*
* And some are commented out with a leading `#` because they have no associated extensions.
* This regexp checks whether a single line matches this format, ignoring lines that are just comments.
* We could also just remove all lines that start with `#` if we want to make the JSON files smaller
* and ignore all mime types without associated extensions.
*/
var re = /^(?:# )?([\w-]+\/[\w\+\.-]+)(?:\s+\w+)*$/
text = text.split('\n')
.filter(Boolean)
.forEach(function (line) {
line = line.trim()
if (!line) return
var match = re.exec(line)
if (!match) return
// remove the leading # and <type> and return all the <ext>s
json[match[1]] = line.replace(/^(?:# )?([\w-]+\/[\w\+\.-]+)/, '')
.split(/\s+/)
.filter(Boolean)
})
fs.writeFileSync('lib/' + path.basename(url).split('.')[0] + '.json',
JSON.stringify(json, null, 2) + '\n')
}
co(function* () {
yield [
get('http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types'),
get('https://raw.githubusercontent.com/broofa/node-mime/master/types/node.types')
]
})()
{ {
"name": "mime-types", "name": "mime-types",
"description": "ultimate mime type utility", "description": "The ultimate javascript content-type utility.",
"version": "0.1.0", "version": "0.1.0",
"author": { "author": {
"name": "Jonathan Ong", "name": "Jonathan Ong",
......
...@@ -20,5 +20,8 @@ ...@@ -20,5 +20,8 @@
], ],
"text/x-handlebars-template": [ "text/x-handlebars-template": [
"hbs" "hbs"
],
"text/jsx": [
"jsx"
] ]
} }
{ {
"name": "mime-types", "name": "mime-types",
"description": "ultimate mime type utility", "description": "The ultimate javascript content-type utility.",
"version": "1.0.0", "version": "1.0.1",
"author": { "author": {
"name": "Jonathan Ong", "name": "Jonathan Ong",
"email": "me@jongleberry.com", "email": "me@jongleberry.com",
...@@ -26,18 +26,17 @@ ...@@ -26,18 +26,17 @@
"mocha": "1", "mocha": "1",
"should": "3" "should": "3"
}, },
"engines": {
"node": ">= 0.8.0"
},
"scripts": { "scripts": {
"test": "make test" "test": "make test"
}, },
"readme": "# mime-types [![Build Status](https://travis-ci.org/expressjs/mime-types.svg?branch=master)](https://travis-ci.org/expressjs/mime-types) [![NPM version](https://badge.fury.io/js/mime-types.svg)](https://badge.fury.io/js/mime-types)\n\nThe ultimate javascript content-type utility.\n\n### Install\n\n```sh\n$ npm install mime-types\n```\n\n#### Similar to [mime](https://github.com/broofa/node-mime) except:\n\n- No `new Mime()` business, so you could do `var lookup = require('mime-types').lookup`.\n- No fallbacks, so do `var type = mime.lookup('unrecognized') || 'application/octet-stream'`.\n- Additional mime types are added such as jade and stylus. Feel free to add more!\n- Browser support via Browserify and Component by converting lists to JSON files.\n\nOtherwise, the API is compatible.\n\n### Adding Types\n\nIf you'd like to add additional types,\nsimply create a PR adding the type to `custom.json` and\na reference link to the [sources](SOURCES.md).\n\nDo __NOT__ edit `mime.json` or `node.json`.\nThose are pulled using `build.js`.\nYou should only touch `custom.json`.\n\n## API\n\n```js\nvar mime = require('mime-types')\n```\n\nAll functions return `false` if input is invalid or not found.\n\n### mime.lookup(path)\n\nLookup the content-type associated with a file.\n\n```js\nmime.lookup('json') // 'application/json'\nmime.lookup('.md') // 'text/x-markdown'\nmime.lookup('file.html') // 'text/html'\nmime.lookup('folder/file.js') // 'application/javascript'\n\nmime.lookup('cats') // false\n```\n\n### mime.contentType(type)\n\nCreate a full content-type header given a content-type or extension.\n\n```js\nmime.contentType('markdown') // 'text/x-markdown; charset=utf-8'\nmime.contentType('file.json') // 'application/json; charset=utf-8'\n```\n\n### mime.extension(type)\n\nGet the default extension for a content-type.\n\n```js\nmime.extension('application/octet-stream') // 'bin'\n```\n\n### mime.charset(type)\n\nLookup the implied default charset of a content-type.\n\n```js\nmime.charset('text/x-markdown') // 'UTF-8'\n```\n\n### mime.types[extension] = type\n\nA map of content-types by extension.\n\n### mime.extensions[type] = [extensions]\n\nA map of extensions by content-type.\n\n### mime.define(types)\n\nGlobally add definitions.\n`types` must be an object of the form:\n\n```js\n{\n \"<content-type>\": [extensions...],\n \"<content-type>\": [extensions...]\n}\n```\n\nSee the `.json` files in `lib/` for examples.\n\n## License\n\n[MIT](LICENSE)\n", "readme": "# mime-types\n[![NPM version](https://badge.fury.io/js/mime-types.svg)](https://badge.fury.io/js/mime-types) [![Build Status](https://travis-ci.org/expressjs/mime-types.svg?branch=master)](https://travis-ci.org/expressjs/mime-types)\n\nThe ultimate javascript content-type utility.\n\n### Install\n\n```sh\n$ npm install mime-types\n```\n\n#### Similar to [node-mime](https://github.com/broofa/node-mime), except:\n\n- __No fallbacks.__ Instead of naively returning the first available type, `mime-types` simply returns `false`, so do `var type = mime.lookup('unrecognized') || 'application/octet-stream'`.\n- No `new Mime()` business, so you could do `var lookup = require('mime-types').lookup`.\n- Additional mime types are added such as jade and stylus. Feel free to add more!\n- Browser support via Browserify and Component by converting lists to JSON files.\n\nOtherwise, the API is compatible.\n\n### Adding Types\n\nIf you'd like to add additional types,\nsimply create a PR adding the type to `custom.json` and\na reference link to the [sources](SOURCES.md).\n\nDo __NOT__ edit `mime.json` or `node.json`.\nThose are pulled using `build.js`.\nYou should only touch `custom.json`.\n\n## API\n\n```js\nvar mime = require('mime-types')\n```\n\nAll functions return `false` if input is invalid or not found.\n\n### mime.lookup(path)\n\nLookup the content-type associated with a file.\n\n```js\nmime.lookup('json') // 'application/json'\nmime.lookup('.md') // 'text/x-markdown'\nmime.lookup('file.html') // 'text/html'\nmime.lookup('folder/file.js') // 'application/javascript'\n\nmime.lookup('cats') // false\n```\n\n### mime.contentType(type)\n\nCreate a full content-type header given a content-type or extension.\n\n```js\nmime.contentType('markdown') // 'text/x-markdown; charset=utf-8'\nmime.contentType('file.json') // 'application/json; charset=utf-8'\n```\n\n### mime.extension(type)\n\nGet the default extension for a content-type.\n\n```js\nmime.extension('application/octet-stream') // 'bin'\n```\n\n### mime.charset(type)\n\nLookup the implied default charset of a content-type.\n\n```js\nmime.charset('text/x-markdown') // 'UTF-8'\n```\n\n### mime.types[extension] = type\n\nA map of content-types by extension.\n\n### mime.extensions[type] = [extensions]\n\nA map of extensions by content-type.\n\n### mime.define(types)\n\nGlobally add definitions.\n`types` must be an object of the form:\n\n```js\n{\n \"<content-type>\": [extensions...],\n \"<content-type>\": [extensions...]\n}\n```\n\nSee the `.json` files in `lib/` for examples.\n\n## License\n\n[MIT](LICENSE)\n",
"readmeFilename": "README.md", "readmeFilename": "README.md",
"bugs": { "bugs": {
"url": "https://github.com/expressjs/mime-types/issues" "url": "https://github.com/expressjs/mime-types/issues"
}, },
"_id": "mime-types@1.0.0", "_id": "mime-types@1.0.1",
"dist": { "_from": "mime-types@~1.0.1"
"shasum": "33e4be5d71804f65b64e01705aef24b8c6c0d76d"
},
"_from": "mime-types@1.0.0",
"_resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.0.tgz"
} }
/**
* Usage: node test.js
*/
var mime = require("..");
var assert = require('assert');
var path = require('path');
function eq(a, b) {
console.log('Test: ' + a + ' === ' + b);
assert.strictEqual.apply(null, arguments);
}
console.log(Object.keys(mime.extensions).length + ' types');
console.log(Object.keys(mime.types).length + ' extensions\n');
//
// Test mime lookups
//
eq('text/plain', mime.lookup('text.txt')); // normal file
eq('text/plain', mime.lookup('TEXT.TXT')); // uppercase
eq('text/plain', mime.lookup('dir/text.txt')); // dir + file
eq('text/plain', mime.lookup('.text.txt')); // hidden file
eq('text/plain', mime.lookup('.txt')); // nameless
eq('text/plain', mime.lookup('txt')); // extension-only
eq('text/plain', mime.lookup('/txt')); // extension-less ()
eq('text/plain', mime.lookup('\\txt')); // Windows, extension-less
// eq('application/octet-stream', mime.lookup('text.nope')); // unrecognized
// eq('fallback', mime.lookup('text.fallback', 'fallback')); // alternate default
//
// Test extensions
//
eq('txt', mime.extension(mime.types.text));
eq('html', mime.extension(mime.types.htm));
eq('bin', mime.extension('application/octet-stream'));
eq('bin', mime.extension('application/octet-stream '));
eq('html', mime.extension(' text/html; charset=UTF-8'));
eq('html', mime.extension('text/html; charset=UTF-8 '));
eq('html', mime.extension('text/html; charset=UTF-8'));
eq('html', mime.extension('text/html ; charset=UTF-8'));
eq('html', mime.extension('text/html;charset=UTF-8'));
eq('html', mime.extension('text/Html;charset=UTF-8'));
eq(false, mime.extension('unrecognized'));
//
// Test node.types lookups
//
eq('application/font-woff', mime.lookup('file.woff'));
eq('application/octet-stream', mime.lookup('file.buffer'));
eq('audio/mp4', mime.lookup('file.m4a'));
eq('font/opentype', mime.lookup('file.otf'));
//
// Test charsets
//
eq('UTF-8', mime.charset('text/plain'));
eq(false, mime.charset(mime.types.js));
eq('UTF-8', mime.charset('application/json'))
eq('UTF-8', mime.charsets.lookup('text/something'));
// eq('fallback', mime.charset('application/octet-stream', 'fallback'));
var assert = require('assert')
var mime = require('..')
var lookup = mime.lookup
var extension = mime.extension
var charset = mime.charset
var contentType = mime.contentType
describe('.lookup()', function () {
it('jade', function () {
assert.equal(lookup('jade'), 'text/jade')
assert.equal(lookup('.jade'), 'text/jade')
assert.equal(lookup('file.jade'), 'text/jade')
assert.equal(lookup('folder/file.jade'), 'text/jade')
})
it('should not error on non-string types', function () {
assert.doesNotThrow(function () {
lookup({ noteven: "once" })
lookup(null)
lookup(true)
lookup(Infinity)
})
})
it('should return false for unknown types', function () {
assert.equal(lookup('.jalksdjflakjsdjfasdf'), false)
})
})
describe('.extension()', function () {
it('should not error on non-string types', function () {
assert.doesNotThrow(function () {
extension({ noteven: "once" })
extension(null)
extension(true)
extension(Infinity)
})
})
it('should return false for unknown types', function () {
assert.equal(extension('.jalksdjflakjsdjfasdf'), false)
})
})
describe('.charset()', function () {
it('should not error on non-string types', function () {
assert.doesNotThrow(function () {
charset({ noteven: "once" })
charset(null)
charset(true)
charset(Infinity)
})
})
it('should return false for unknown types', function () {
assert.equal(charset('.jalksdjflakjsdjfasdf'), false)
})
})
describe('.contentType()', function () {
it('html', function () {
assert.equal(contentType('html'), 'text/html; charset=utf-8')
})
it('text/html; charset=ascii', function () {
assert.equal(contentType('text/html; charset=ascii'), 'text/html; charset=ascii')
})
it('json', function () {
assert.equal(contentType('json'), 'application/json; charset=utf-8')
})
it('application/json', function () {
assert.equal(contentType('application/json'), 'application/json; charset=utf-8')
})
it('jade', function () {
assert.equal(contentType('jade'), 'text/jade; charset=utf-8')
})
it('should not error on non-string types', function () {
assert.doesNotThrow(function () {
contentType({ noteven: "once" })
contentType(null)
contentType(true)
contentType(Infinity)
})
})
it('should return false for unknown types', function () {
assert.equal(contentType('.jalksdjflakjsdjfasdf'), false)
})
})
{ {
"name": "type-is", "name": "type-is",
"description": "Infer the content-type of a request.", "description": "Infer the content-type of a request.",
"version": "1.2.1", "version": "1.3.2",
"author": { "author": {
"name": "Jonathan Ong", "name": "Jonathan Ong",
"email": "me@jongleberry.com", "email": "me@jongleberry.com",
...@@ -19,9 +19,11 @@ ...@@ -19,9 +19,11 @@
"url": "git://github.com/expressjs/type-is" "url": "git://github.com/expressjs/type-is"
}, },
"dependencies": { "dependencies": {
"mime-types": "1.0.0" "media-typer": "0.2.0",
"mime-types": "~1.0.1"
}, },
"devDependencies": { "devDependencies": {
"istanbul": "0.2.11",
"mocha": "*", "mocha": "*",
"should": "*" "should": "*"
}, },
...@@ -29,17 +31,19 @@ ...@@ -29,17 +31,19 @@
"node": ">= 0.8" "node": ">= 0.8"
}, },
"scripts": { "scripts": {
"test": "mocha --require should --reporter spec --bail" "test": "mocha --require should --reporter spec --check-leaks --bail test/",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/"
}, },
"readme": "# type-is [![Build Status](https://travis-ci.org/expressjs/type-is.svg?branch=master)](https://travis-ci.org/expressjs/type-is) [![NPM version](https://badge.fury.io/js/type-is.svg)](https://badge.fury.io/js/type-is)\n\nInfer the content-type of a request.\n\n### Install\n\n```sh\n$ npm install type-is\n```\n\n## API\n\n```js\nvar http = require('http')\nvar is = require('type-is')\n\nhttp.createServer(function (req, res) {\n is(req, ['text/*'])\n})\n```\n\n### type = is(request, types)\n\n`request` is the node HTTP request. `types` is an array of types.\n\n```js\n// req.headers.content-type = 'application/json'\n\nis(req, ['json']) // 'json'\nis(req, ['html', 'json']) // 'json'\nis(req, ['application/*']) // 'application/json'\nis(req, ['application/json']) // 'application/json'\n\nis(req, ['html']) // false\n```\n\n#### Each type can be:\n\n- An extension name such as `json`. This name will be returned if matched.\n- A mime type such as `application/json`.\n- A mime type with a wildcard such as `*/json` or `application/*`. The full mime type will be returned if matched\n- A suffix such as `+json`. This can be combined with a wildcard such as `*/vnd+json` or `application/*+json`. The full mime type will be returned if matched.\n\n`false` will be returned if no type matches.\n\n## Examples\n\n#### Example body parser\n\n```js\nvar is = require('type-is');\nvar parse = require('body');\nvar busboy = require('busboy');\n\nfunction bodyParser(req, res, next) {\n var hasRequestBody = 'content-type' in req.headers\n || 'transfer-encoding' in req.headers;\n if (!hasRequestBody) return next();\n\n switch (is(req, ['urlencoded', 'json', 'multipart'])) {\n case 'urlencoded':\n // parse urlencoded body\n break\n case 'json':\n // parse json body\n break\n case 'multipart':\n // parse multipart body\n break\n default:\n // 415 error code\n }\n}\n```\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2013 Jonathan Ong me@jongleberry.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n", "readme": "# type-is\n\n[![NPM version](https://badge.fury.io/js/type-is.svg)](https://badge.fury.io/js/type-is)\n[![Build Status](https://travis-ci.org/expressjs/type-is.svg?branch=master)](https://travis-ci.org/expressjs/type-is)\n[![Coverage Status](https://img.shields.io/coveralls/expressjs/type-is.svg?branch=master)](https://coveralls.io/r/expressjs/type-is)\n\nInfer the content-type of a request.\n\n### Install\n\n```sh\n$ npm install type-is\n```\n\n## API\n\n```js\nvar http = require('http')\nvar is = require('type-is')\n\nhttp.createServer(function (req, res) {\n var istext = is(req, ['text/*'])\n res.end('you ' + (istext ? 'sent' : 'did not send') + ' me text')\n})\n```\n\n### type = is(request, types)\n\n`request` is the node HTTP request. `types` is an array of types.\n\n```js\n// req.headers.content-type = 'application/json'\n\nis(req, ['json']) // 'json'\nis(req, ['html', 'json']) // 'json'\nis(req, ['application/*']) // 'application/json'\nis(req, ['application/json']) // 'application/json'\n\nis(req, ['html']) // false\n```\n\n#### Each type can be:\n\n- An extension name such as `json`. This name will be returned if matched.\n- A mime type such as `application/json`.\n- A mime type with a wildcard such as `*/json` or `application/*`. The full mime type will be returned if matched\n- A suffix such as `+json`. This can be combined with a wildcard such as `*/vnd+json` or `application/*+json`. The full mime type will be returned if matched.\n\n`false` will be returned if no type matches.\n\n## Examples\n\n#### Example body parser\n\n```js\nvar is = require('type-is');\nvar parse = require('body');\nvar busboy = require('busboy');\n\nfunction bodyParser(req, res, next) {\n if (!is.hasBody(req)) return next();\n\n switch (is(req, ['urlencoded', 'json', 'multipart'])) {\n case 'urlencoded':\n // parse urlencoded body\n break\n case 'json':\n // parse json body\n break\n case 'multipart':\n // parse multipart body\n break\n default:\n // 415 error code\n }\n}\n```\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2013 Jonathan Ong me@jongleberry.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n",
"readmeFilename": "README.md", "readmeFilename": "README.md",
"bugs": { "bugs": {
"url": "https://github.com/expressjs/type-is/issues" "url": "https://github.com/expressjs/type-is/issues"
}, },
"_id": "type-is@1.2.1", "_id": "type-is@1.3.2",
"dist": { "dist": {
"shasum": "ce92daaf26b7e04e10bcf83489774fb6703fccaf" "shasum": "c42636e2d6dde79ec18f8d389d0100dc3658b281"
}, },
"_from": "type-is@1.2.1", "_from": "type-is@~1.3.2",
"_resolved": "https://registry.npmjs.org/type-is/-/type-is-1.2.1.tgz" "_resolved": "https://registry.npmjs.org/type-is/-/type-is-1.3.2.tgz"
} }
{ {
"name": "express", "name": "express",
"description": "Sinatra inspired web development framework", "description": "Fast, unopinionated, minimalist web framework",
"version": "4.4.5", "version": "4.5.0",
"author": { "author": {
"name": "TJ Holowaychuk", "name": "TJ Holowaychuk",
"email": "tj@vision-media.ca" "email": "tj@vision-media.ca"
...@@ -48,17 +48,20 @@ ...@@ -48,17 +48,20 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"accepts": "~1.0.5", "accepts": "~1.0.7",
"buffer-crc32": "0.2.3", "buffer-crc32": "0.2.3",
"debug": "1.0.2", "debug": "1.0.2",
"depd": "0.3.0",
"escape-html": "1.0.1", "escape-html": "1.0.1",
"finalhandler": "0.0.2",
"media-typer": "0.2.0",
"methods": "1.0.1", "methods": "1.0.1",
"parseurl": "1.0.1", "parseurl": "1.0.1",
"proxy-addr": "1.0.1", "proxy-addr": "1.0.1",
"range-parser": "1.0.0", "range-parser": "1.0.0",
"send": "0.4.3", "send": "0.5.0",
"serve-static": "1.2.3", "serve-static": "~1.3.0",
"type-is": "1.2.1", "type-is": "~1.3.2",
"vary": "0.1.0", "vary": "0.1.0",
"cookie": "0.1.2", "cookie": "0.1.2",
"fresh": "0.2.2", "fresh": "0.2.2",
...@@ -70,7 +73,7 @@ ...@@ -70,7 +73,7 @@
}, },
"devDependencies": { "devDependencies": {
"after": "0.8.1", "after": "0.8.1",
"istanbul": "0.2.10", "istanbul": "0.2.14",
"mocha": "~1.20.1", "mocha": "~1.20.1",
"should": "~4.0.4", "should": "~4.0.4",
"supertest": "~0.13.0", "supertest": "~0.13.0",
...@@ -78,12 +81,12 @@ ...@@ -78,12 +81,12 @@
"ejs": "~1.0.0", "ejs": "~1.0.0",
"jade": "~1.3.1", "jade": "~1.3.1",
"marked": "0.3.2", "marked": "0.3.2",
"multiparty": "~3.2.4",
"hjs": "~0.0.6", "hjs": "~0.0.6",
"body-parser": "~1.4.3", "body-parser": "~1.4.3",
"cookie-parser": "~1.3.1", "cookie-parser": "~1.3.1",
"express-session": "~1.5.0", "express-session": "~1.6.1",
"method-override": "2.0.2", "method-override": "2.0.2",
"multiparty": "~3.3.0",
"morgan": "1.1.1", "morgan": "1.1.1",
"vhost": "2.0.0" "vhost": "2.0.0"
}, },
...@@ -96,15 +99,15 @@ ...@@ -96,15 +99,15 @@
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/ test/acceptance/", "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/ test/acceptance/",
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/ test/acceptance/" "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/ test/acceptance/"
}, },
"readme": "[![express logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](http://expressjs.com/)\n\n Fast, unopinionated, minimalist web framework for [node](http://nodejs.org).\n\n [![NPM version](https://badge.fury.io/js/express.svg)](http://badge.fury.io/js/express)\n [![Build Status](https://travis-ci.org/visionmedia/express.svg?branch=master)](https://travis-ci.org/visionmedia/express)\n [![Coverage Status](https://img.shields.io/coveralls/visionmedia/express.svg)](https://coveralls.io/r/visionmedia/express)\n [![Gittip](http://img.shields.io/gittip/visionmedia.svg)](https://www.gittip.com/visionmedia/)\n\n```js\nvar express = require('express');\nvar app = express();\n\napp.get('/', function(req, res){\n res.send('Hello World');\n});\n\napp.listen(3000);\n```\n\n**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/visionmedia/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/visionmedia/express/wiki/New-features-in-4.x).\n\n## Installation\n\n $ npm install express\n\n## Quick Start\n\n The quickest way to get started with express is to utilize the executable [`express(1)`](http://github.com/expressjs/generator) to generate an application as shown below:\n \n Install the executable. The executable's major version will match Express's:\n \n $ npm install -g express-generator@3\n\n Create the app:\n\n $ express /tmp/foo && cd /tmp/foo\n\n Install dependencies:\n\n $ npm install\n\n Start the server:\n\n $ npm start\n\n## Features\n\n * Robust routing\n * HTTP helpers (redirection, caching, etc)\n * View system supporting 14+ template engines\n * Content negotiation\n * Focus on high performance\n * Executable for generating applications quickly\n * High test coverage\n\n## Philosophy\n\n The Express philosophy is to provide small, robust tooling for HTTP servers, making\n it a great solution for single page applications, web sites, hybrids, or public\n HTTP APIs.\n\n Express does not force you to use any specific ORM or template engine. With support for over\n 14 template engines via [Consolidate.js](http://github.com/visionmedia/consolidate.js),\n you can quickly craft your perfect framework.\n\n## More Information\n\n * [Website and Documentation](http://expressjs.com/) stored at [visionmedia/expressjs.com](https://github.com/visionmedia/expressjs.com)\n * Join #express on freenode\n * [Google Group](http://groups.google.com/group/express-js) for discussion\n * Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) and [defunctzombie](https://twitter.com/defunctzombie) on twitter for updates\n * Visit the [Wiki](http://github.com/visionmedia/express/wiki)\n * [Русскоязычная документация](http://jsman.ru/express/)\n * Run express examples [online](https://runnable.com/express)\n\n## Viewing Examples\n\nClone the Express repo, then install the dev dependencies to install all the example / test suite dependencies:\n\n $ git clone git://github.com/visionmedia/express.git --depth 1\n $ cd express\n $ npm install\n\nThen run whichever tests you want:\n\n $ node examples/content-negotiation\n\nYou can also view live examples here:\n\n<a href=\"https://runnable.com/express\" target=\"_blank\"><img src=\"https://runnable.com/external/styles/assets/runnablebtn.png\" style=\"width:67px;height:25px;\"></a>\n\n## Running Tests\n\nTo run the test suite, first invoke the following command within the repo, installing the development dependencies:\n\n $ npm install\n\nThen run the tests:\n\n```sh\n$ npm test\n```\n\n## Contributors\n \n Author: [TJ Holowaychuk](http://github.com/visionmedia) \n Lead Maintainer: [Roman Shtylman](https://github.com/defunctzombie) \n Contributors: https://github.com/visionmedia/express/graphs/contributors \n\n## License\n\nMIT\n", "readme": "[![Express Logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](https://expressjs.com/)\n\n Fast, unopinionated, minimalist web framework for [node](https://nodejs.org).\n\n [![NPM Version](https://badge.fury.io/js/express.svg)](https://badge.fury.io/js/express)\n [![Build Status](https://travis-ci.org/visionmedia/express.svg?branch=master)](https://travis-ci.org/visionmedia/express)\n [![Coverage Status](https://img.shields.io/coveralls/visionmedia/express.svg)](https://coveralls.io/r/visionmedia/express)\n [![Gittip](https://img.shields.io/gittip/visionmedia.svg)](https://www.gittip.com/visionmedia/)\n\n```js\nvar express = require('express')\nvar app = express()\n\napp.get('/', function (req, res) {\n res.send('Hello World')\n})\n\napp.listen(3000)\n```\n\n **PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/visionmedia/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/visionmedia/express/wiki/New-features-in-4.x).\n\n### Installation\n\n```bash\n$ npm install express\n```\n\n## Quick Start\n\n The quickest way to get started with express is to utilize the executable [`express(1)`](https://github.com/expressjs/generator) to generate an application as shown below:\n\n Install the executable. The executable's major version will match Express's:\n\n```bash\n$ npm install -g express-generator@4\n```\n\n Create the app:\n\n```bash\n$ express /tmp/foo && cd /tmp/foo\n```\n\n Install dependencies:\n\n```bash\n$ npm install\n```\n\n Start the server:\n\n```bash\n$ npm start\n```\n\n## Features\n\n * Robust routing\n * HTTP helpers (redirection, caching, etc)\n * View system supporting 14+ template engines\n * Content negotiation\n * Focus on high performance\n * Executable for generating applications quickly\n * High test coverage\n\n## Philosophy\n\n The Express philosophy is to provide small, robust tooling for HTTP servers, making\n it a great solution for single page applications, web sites, hybrids, or public\n HTTP APIs.\n\n Express does not force you to use any specific ORM or template engine. With support for over\n 14 template engines via [Consolidate.js](https://github.com/visionmedia/consolidate.js),\n you can quickly craft your perfect framework.\n\n## More Information\n\n * [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/visionmedia/expressjs.com)]\n * [Github Organization](https://github.com/expressjs) for Official Middleware & Modules\n * [#express](https://webchat.freenode.net/?channels=express) on freenode IRC\n * Visit the [Wiki](https://github.com/visionmedia/express/wiki)\n * [Google Group](https://groups.google.com/group/express-js) for discussion\n * [Русскоязычная документация](http://jsman.ru/express/)\n * Run express examples [online](https://runnable.com/express)\n\n## Viewing Examples\n\n Clone the Express repo, then install the dev dependencies to install all the example / test suite dependencies:\n\n```bash\n$ git clone git://github.com/visionmedia/express.git --depth 1\n$ cd express\n$ npm install\n```\n\n Then run whichever example you want:\n\n $ node examples/content-negotiation\n\n You can also view live examples here:\n\n <a href=\"https://runnable.com/express\" target=\"_blank\"><img src=\"https://runnable.com/external/styles/assets/runnablebtn.png\" style=\"width:67px;height:25px;\"></a>\n\n## Running Tests\n\n To run the test suite, first invoke the following command within the repo, installing the development dependencies:\n\n```bash\n$ npm install\n```\n\n Then run the tests:\n\n```bash\n$ npm test\n```\n\n### Contributors\n\n * Author: [TJ Holowaychuk](https://github.com/visionmedia)\n * Lead Maintainer: [Douglas Christopher Wilson](https://github.com/dougwilson)\n * [All Contributors](https://github.com/visionmedia/express/graphs/contributors)\n\n### License\n\n [MIT](LICENSE)\n",
"readmeFilename": "Readme.md", "readmeFilename": "Readme.md",
"bugs": { "bugs": {
"url": "https://github.com/visionmedia/express/issues" "url": "https://github.com/visionmedia/express/issues"
}, },
"_id": "express@4.4.5", "_id": "express@4.5.0",
"dist": { "dist": {
"shasum": "95c69de656eb00e90c5ef8e3e0810c5169f21444" "shasum": "9af93a6d8d1bab07b14419fed850dade23380a5b"
}, },
"_from": "express@4.x", "_from": "express@4.x",
"_resolved": "https://registry.npmjs.org/express/-/express-4.4.5.tgz" "_resolved": "https://registry.npmjs.org/express/-/express-4.5.0.tgz"
} }
1.0.7 / 2014-07-04
==================
* Fix wrong type returned from `type` when match after unknown extension
1.0.6 / 2014-06-24 1.0.6 / 2014-06-24
================== ==================
......
...@@ -60,8 +60,8 @@ Accepts.prototype.types = function (types) { ...@@ -60,8 +60,8 @@ Accepts.prototype.types = function (types) {
var n = this.negotiator; var n = this.negotiator;
if (!types.length) return n.mediaTypes(); if (!types.length) return n.mediaTypes();
if (!this.headers.accept) return types[0]; if (!this.headers.accept) return types[0];
var mimes = types.map(extToMime).filter(validMime); var mimes = types.map(extToMime);
var accepts = n.mediaTypes(mimes); var accepts = n.mediaTypes(mimes.filter(validMime));
var first = accepts[0]; var first = accepts[0];
if (!first) return false; if (!first) return false;
return types[mimes.indexOf(first)]; return types[mimes.indexOf(first)];
......
...@@ -45,9 +45,5 @@ ...@@ -45,9 +45,5 @@
}, },
"dependencies": {}, "dependencies": {},
"_id": "negotiator@0.4.7", "_id": "negotiator@0.4.7",
"dist": { "_from": "negotiator@0.4.7"
"shasum": "8273ad98ad1c14fed21daa9a404fb6a102d47305"
},
"_from": "negotiator@0.4.7",
"_resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.7.tgz"
} }
{ {
"name": "accepts", "name": "accepts",
"description": "Higher-level content negotiation", "description": "Higher-level content negotiation",
"version": "1.0.6", "version": "1.0.7",
"author": { "author": {
"name": "Jonathan Ong", "name": "Jonathan Ong",
"email": "me@jongleberry.com", "email": "me@jongleberry.com",
...@@ -34,10 +34,10 @@ ...@@ -34,10 +34,10 @@
"bugs": { "bugs": {
"url": "https://github.com/expressjs/accepts/issues" "url": "https://github.com/expressjs/accepts/issues"
}, },
"_id": "accepts@1.0.6", "_id": "accepts@1.0.7",
"dist": { "dist": {
"shasum": "fc9be3e5812513c8e758ea54d87f07275a5529d5" "shasum": "85a518a6fac930ecd86ae82149202b4f4ab842da"
}, },
"_from": "accepts@~1.0.5", "_from": "accepts@~1.0.5",
"_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.0.6.tgz" "_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.0.7.tgz"
} }
...@@ -24,6 +24,5 @@ ...@@ -24,6 +24,5 @@
"url": "https://github.com/component/escape-html/issues" "url": "https://github.com/component/escape-html/issues"
}, },
"_id": "escape-html@1.0.1", "_id": "escape-html@1.0.1",
"_from": "escape-html@1.0.1", "_from": "escape-html@1.0.1"
"scripts": {}
} }
...@@ -43,10 +43,6 @@ ...@@ -43,10 +43,6 @@
"url": "https://github.com/visionmedia/debug/issues" "url": "https://github.com/visionmedia/debug/issues"
}, },
"_id": "debug@1.0.2", "_id": "debug@1.0.2",
"dist": {
"shasum": "a1c1da1278c90866cc063eff49db9f0a8a0a211e"
},
"_from": "debug@1.0.2", "_from": "debug@1.0.2",
"_resolved": "https://registry.npmjs.org/debug/-/debug-1.0.2.tgz",
"scripts": {} "scripts": {}
} }
...@@ -23,6 +23,10 @@ ...@@ -23,6 +23,10 @@
"url": "https://github.com/guille/ms.js/issues" "url": "https://github.com/guille/ms.js/issues"
}, },
"_id": "ms@0.6.2", "_id": "ms@0.6.2",
"dist": {
"shasum": "f13296ecf600d296c9f2ff2b61f2f9eb12a69c79"
},
"_from": "ms@0.6.2", "_from": "ms@0.6.2",
"_resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz",
"scripts": {} "scripts": {}
} }
...@@ -51,9 +51,5 @@ ...@@ -51,9 +51,5 @@
"url": "https://github.com/visionmedia/send/issues" "url": "https://github.com/visionmedia/send/issues"
}, },
"_id": "send@0.5.0", "_id": "send@0.5.0",
"dist": { "_from": "send@0.5.0"
"shasum": "30dd1f72540f8eaeda901a3ffd6336a7719d94fe"
},
"_from": "send@0.5.0",
"_resolved": "https://registry.npmjs.org/send/-/send-0.5.0.tgz"
} }
...@@ -36,9 +36,5 @@ ...@@ -36,9 +36,5 @@
"url": "https://github.com/expressjs/serve-static/issues" "url": "https://github.com/expressjs/serve-static/issues"
}, },
"_id": "serve-static@1.3.0", "_id": "serve-static@1.3.0",
"dist": { "_from": "serve-static@*"
"shasum": "e35776221565df27ce3895a0d872ec5177647cc1"
},
"_from": "serve-static@*",
"_resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.3.0.tgz"
} }
...@@ -41,9 +41,5 @@ ...@@ -41,9 +41,5 @@
"url": "https://github.com/visionmedia/debug/issues" "url": "https://github.com/visionmedia/debug/issues"
}, },
"_id": "debug@0.7.4", "_id": "debug@0.7.4",
"dist": { "_from": "debug@0.7.4"
"shasum": "6d61ff0bcdda31e2135e2cc0d7d6f0aa80b09c19"
},
"_from": "debug@0.7.4",
"_resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz"
} }
...@@ -22,9 +22,5 @@ ...@@ -22,9 +22,5 @@
"readme": "\n# debug\n\n tiny node.js debugging utility.\n\n## Installation\n\n```\n$ npm install debug\n```\n\n## Example\n\n This module is modelled after node core's debugging technique, allowing you to enable one or more topic-specific debugging functions, for example core does the following within many modules:\n\n```js\nvar debug;\nif (process.env.NODE_DEBUG && /cluster/.test(process.env.NODE_DEBUG)) {\n debug = function(x) {\n var prefix = process.pid + ',' +\n (process.env.NODE_WORKER_ID ? 'Worker' : 'Master');\n console.error(prefix, x);\n };\n} else {\n debug = function() { };\n}\n```\n\n This concept is extremely simple but it works well. With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.\n \nExample _app.js_:\n\n```js\nvar debug = require('debug')('http')\n , http = require('http')\n , name = 'My App';\n\n// fake app\n\ndebug('booting %s', name);\n\nhttp.createServer(function(req, res){\n debug(req.method + ' ' + req.url);\n res.end('hello\\n');\n}).listen(3000, function(){\n debug('listening');\n});\n\n// fake worker of some kind\n\nrequire('./worker');\n```\n\nExample _worker.js_:\n\n```js\nvar debug = require('debug')('worker');\n\nsetInterval(function(){\n debug('doing some work');\n}, 1000);\n```\n\n The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:\n\n ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)\n\n ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)\n\n## Millisecond diff\n\n When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the \"+NNNms\" will show you how much time was spent between calls.\n\n ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)\n\n When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:\n \n ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)\n\n## Conventions\n\n If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use \":\" to separate features. For example \"bodyParser\" from Connect would then be \"connect:bodyParser\". \n\n## Wildcards\n\n The \"*\" character may be used as a wildcard. Suppose for example your library has debuggers named \"connect:bodyParser\", \"connect:compress\", \"connect:session\", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.\n\n You can also exclude specific debuggers by prefixing them with a \"-\" character. For example, `DEBUG=* -connect:*` would include all debuggers except those starting with \"connect:\".\n\n## Browser support\n\n Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. \n\n```js\na = debug('worker:a');\nb = debug('worker:b');\n\nsetInterval(function(){\n a('doing some work');\n}, 1000);\n\nsetInterval(function(){\n a('doing some work');\n}, 1200);\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", "readme": "\n# debug\n\n tiny node.js debugging utility.\n\n## Installation\n\n```\n$ npm install debug\n```\n\n## Example\n\n This module is modelled after node core's debugging technique, allowing you to enable one or more topic-specific debugging functions, for example core does the following within many modules:\n\n```js\nvar debug;\nif (process.env.NODE_DEBUG && /cluster/.test(process.env.NODE_DEBUG)) {\n debug = function(x) {\n var prefix = process.pid + ',' +\n (process.env.NODE_WORKER_ID ? 'Worker' : 'Master');\n console.error(prefix, x);\n };\n} else {\n debug = function() { };\n}\n```\n\n This concept is extremely simple but it works well. With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.\n \nExample _app.js_:\n\n```js\nvar debug = require('debug')('http')\n , http = require('http')\n , name = 'My App';\n\n// fake app\n\ndebug('booting %s', name);\n\nhttp.createServer(function(req, res){\n debug(req.method + ' ' + req.url);\n res.end('hello\\n');\n}).listen(3000, function(){\n debug('listening');\n});\n\n// fake worker of some kind\n\nrequire('./worker');\n```\n\nExample _worker.js_:\n\n```js\nvar debug = require('debug')('worker');\n\nsetInterval(function(){\n debug('doing some work');\n}, 1000);\n```\n\n The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:\n\n ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)\n\n ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)\n\n## Millisecond diff\n\n When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the \"+NNNms\" will show you how much time was spent between calls.\n\n ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)\n\n When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:\n \n ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)\n\n## Conventions\n\n If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use \":\" to separate features. For example \"bodyParser\" from Connect would then be \"connect:bodyParser\". \n\n## Wildcards\n\n The \"*\" character may be used as a wildcard. Suppose for example your library has debuggers named \"connect:bodyParser\", \"connect:compress\", \"connect:session\", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.\n\n You can also exclude specific debuggers by prefixing them with a \"-\" character. For example, `DEBUG=* -connect:*` would include all debuggers except those starting with \"connect:\".\n\n## Browser support\n\n Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. \n\n```js\na = debug('worker:a');\nb = debug('worker:b');\n\nsetInterval(function(){\n a('doing some work');\n}, 1000);\n\nsetInterval(function(){\n a('doing some work');\n}, 1200);\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
"readmeFilename": "Readme.md", "readmeFilename": "Readme.md",
"_id": "debug@0.6.0", "_id": "debug@0.6.0",
"dist": { "_from": "debug@0.6.0"
"shasum": "f56cb9d82bc76b3df607b6c27936d28e7c939de5"
},
"_from": "debug@0.6.0",
"_resolved": "https://registry.npmjs.org/debug/-/debug-0.6.0.tgz"
} }
...@@ -35,9 +35,5 @@ ...@@ -35,9 +35,5 @@
"url": "https://github.com/LearnBoost/engine.io-parser/issues" "url": "https://github.com/LearnBoost/engine.io-parser/issues"
}, },
"_id": "engine.io-parser@1.0.6", "_id": "engine.io-parser@1.0.6",
"dist": { "_from": "engine.io-parser@1.0.6"
"shasum": "076906199bcf2195521947dd6e831c5bfcbfc5d5"
},
"_from": "engine.io-parser@1.0.6",
"_resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.0.6.tgz"
} }
...@@ -56,9 +56,5 @@ ...@@ -56,9 +56,5 @@
"url": "https://github.com/einaros/ws/issues" "url": "https://github.com/einaros/ws/issues"
}, },
"_id": "ws@0.4.31", "_id": "ws@0.4.31",
"dist": { "_from": "ws@0.4.31"
"shasum": "fed17bd81b4cc99cb79b75ffd49953fd3e7bf0d6"
},
"_from": "ws@0.4.31",
"_resolved": "https://registry.npmjs.org/ws/-/ws-0.4.31.tgz"
} }
...@@ -52,9 +52,5 @@ ...@@ -52,9 +52,5 @@
"url": "https://github.com/LearnBoost/engine.io/issues" "url": "https://github.com/LearnBoost/engine.io/issues"
}, },
"_id": "engine.io@1.3.1", "_id": "engine.io@1.3.1",
"dist": { "_from": "engine.io@1.3.1"
"shasum": "889c501bab3765ede9fd6681e20e10557db72ebf"
},
"_from": "engine.io@1.3.1",
"_resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.3.1.tgz"
} }
...@@ -32,9 +32,5 @@ ...@@ -32,9 +32,5 @@
"url": "https://github.com/juliangruber/isarray/issues" "url": "https://github.com/juliangruber/isarray/issues"
}, },
"_id": "isarray@0.0.1", "_id": "isarray@0.0.1",
"dist": { "_from": "isarray@0.0.1"
"shasum": "dc2d43f65e32bd485997e422c73ade69f488882f"
},
"_from": "isarray@0.0.1",
"_resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
} }
...@@ -16,9 +16,5 @@ ...@@ -16,9 +16,5 @@
"readme": "has-binarydata.js\n=================\n\nSimple module to test if an object contains binary data\n", "readme": "has-binarydata.js\n=================\n\nSimple module to test if an object contains binary data\n",
"readmeFilename": "README.md", "readmeFilename": "README.md",
"_id": "has-binary-data@0.1.1", "_id": "has-binary-data@0.1.1",
"dist": { "_from": "has-binary-data@0.1.1"
"shasum": "394a850da71bf91a8bd02797ccec161946eeaf93"
},
"_from": "has-binary-data@0.1.1",
"_resolved": "https://registry.npmjs.org/has-binary-data/-/has-binary-data-0.1.1.tgz"
} }
...@@ -32,9 +32,5 @@ ...@@ -32,9 +32,5 @@
"url": "https://github.com/juliangruber/isarray/issues" "url": "https://github.com/juliangruber/isarray/issues"
}, },
"_id": "isarray@0.0.1", "_id": "isarray@0.0.1",
"dist": { "_from": "isarray@0.0.1"
"shasum": "dc2d43f65e32bd485997e422c73ade69f488882f"
},
"_from": "isarray@0.0.1",
"_resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
} }
...@@ -25,9 +25,5 @@ ...@@ -25,9 +25,5 @@
"url": "https://github.com/component/emitter/issues" "url": "https://github.com/component/emitter/issues"
}, },
"_id": "component-emitter@1.1.2", "_id": "component-emitter@1.1.2",
"dist": { "_from": "component-emitter@1.1.2"
"shasum": "8a6787a888a95dd6cfd203dbd1b752a68e2d6b50"
},
"_from": "component-emitter@1.1.2",
"_resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz"
} }
...@@ -35,9 +35,5 @@ ...@@ -35,9 +35,5 @@
"url": "https://github.com/LearnBoost/engine.io-parser/issues" "url": "https://github.com/LearnBoost/engine.io-parser/issues"
}, },
"_id": "engine.io-parser@1.0.6", "_id": "engine.io-parser@1.0.6",
"dist": { "_from": "engine.io-parser@1.0.6"
"shasum": "076906199bcf2195521947dd6e831c5bfcbfc5d5"
},
"_from": "engine.io-parser@1.0.6",
"_resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.0.6.tgz"
} }
...@@ -15,5 +15,9 @@ ...@@ -15,5 +15,9 @@
}, },
"readme": "ERROR: No README data found!", "readme": "ERROR: No README data found!",
"_id": "parsejson@0.0.1", "_id": "parsejson@0.0.1",
"_from": "parsejson@0.0.1" "dist": {
"shasum": "ecd00fd9f6b1621b8fef984468914ca3bcf5dc2b"
},
"_from": "parsejson@0.0.1",
"_resolved": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.1.tgz"
} }
...@@ -15,5 +15,9 @@ ...@@ -15,5 +15,9 @@
}, },
"readme": "ERROR: No README data found!", "readme": "ERROR: No README data found!",
"_id": "parseqs@0.0.2", "_id": "parseqs@0.0.2",
"_from": "parseqs@0.0.2" "dist": {
"shasum": "ce835afb7800568fd4a16ad59ba8378e0831e994"
},
"_from": "parseqs@0.0.2",
"_resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.2.tgz"
} }
...@@ -56,9 +56,5 @@ ...@@ -56,9 +56,5 @@
"url": "https://github.com/einaros/ws/issues" "url": "https://github.com/einaros/ws/issues"
}, },
"_id": "ws@0.4.31", "_id": "ws@0.4.31",
"dist": { "_from": "ws@0.4.31"
"shasum": "fed17bd81b4cc99cb79b75ffd49953fd3e7bf0d6"
},
"_from": "ws@0.4.31",
"_resolved": "https://registry.npmjs.org/ws/-/ws-0.4.31.tgz"
} }
...@@ -32,9 +32,5 @@ ...@@ -32,9 +32,5 @@
"url": "https://github.com/juliangruber/isarray/issues" "url": "https://github.com/juliangruber/isarray/issues"
}, },
"_id": "isarray@0.0.1", "_id": "isarray@0.0.1",
"dist": { "_from": "isarray@0.0.1"
"shasum": "dc2d43f65e32bd485997e422c73ade69f488882f"
},
"_from": "isarray@0.0.1",
"_resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment