mirror of
https://github.com/expressjs/express.git
synced 2026-02-26 08:45:36 +00:00
Compare commits
84 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7119f2b16d | ||
|
|
a57efea173 | ||
|
|
4a4ca7347a | ||
|
|
570f60d36e | ||
|
|
d13e613584 | ||
|
|
9204e1f42a | ||
|
|
ddac571fdf | ||
|
|
982d24b475 | ||
|
|
ea427c1bb4 | ||
|
|
0bd6c311cf | ||
|
|
7f606ebf29 | ||
|
|
c652cf7eed | ||
|
|
19fd6f85b0 | ||
|
|
b6c5b0511f | ||
|
|
0e42a37edd | ||
|
|
b24ed15878 | ||
|
|
15590d75b2 | ||
|
|
e8b471ff4f | ||
|
|
767db01b79 | ||
|
|
696e150f0a | ||
|
|
819265c7ae | ||
|
|
baf8b14a71 | ||
|
|
06e7685d65 | ||
|
|
9f4968aaa3 | ||
|
|
afea3c0ae8 | ||
|
|
edaabe66cf | ||
|
|
f724730e1a | ||
|
|
e49d0dc9e3 | ||
|
|
e7a3fbaf48 | ||
|
|
928952e7f0 | ||
|
|
a28b7a85cf | ||
|
|
3fc8dc54ee | ||
|
|
0d77305a1a | ||
|
|
323c185079 | ||
|
|
1d0da9036b | ||
|
|
683ba1cd75 | ||
|
|
e4ff5281c9 | ||
|
|
7414a1f463 | ||
|
|
916c53737d | ||
|
|
b2382a7336 | ||
|
|
f684a64df7 | ||
|
|
5d03d0eac8 | ||
|
|
544c6665f5 | ||
|
|
cf8005e63f | ||
|
|
25ef8425d2 | ||
|
|
577cc1d1a0 | ||
|
|
3c87a6aede | ||
|
|
7c1f90bf16 | ||
|
|
7bcf5f5085 | ||
|
|
abe0ffa311 | ||
|
|
b601d64203 | ||
|
|
f381f2d9b6 | ||
|
|
12507cfcd0 | ||
|
|
185e327e29 | ||
|
|
c468f5ff20 | ||
|
|
9bb47fba30 | ||
|
|
78d489d730 | ||
|
|
8ffb9f9477 | ||
|
|
9cb147370e | ||
|
|
75422c16bf | ||
|
|
e66667e465 | ||
|
|
7d6208e0af | ||
|
|
2a105df9f2 | ||
|
|
9c731f1883 | ||
|
|
5a4e9125de | ||
|
|
9db1367c2d | ||
|
|
73c5533e66 | ||
|
|
3b1f747f96 | ||
|
|
9e9827d236 | ||
|
|
a76d508424 | ||
|
|
f881784e9b | ||
|
|
5af625903f | ||
|
|
dc94f305cc | ||
|
|
8060a49c6c | ||
|
|
2fd31f6ea6 | ||
|
|
9cf7bba8f0 | ||
|
|
2e257d1cf7 | ||
|
|
56831d7799 | ||
|
|
6d65ae5ba6 | ||
|
|
c919b4a573 | ||
|
|
fe6f392c2d | ||
|
|
3b34a537ee | ||
|
|
ad79ce9c4b | ||
|
|
721f6388c3 |
268
History.md
268
History.md
@@ -1,8 +1,274 @@
|
||||
3.16.4 / 2014-08-10
|
||||
===================
|
||||
|
||||
* Fix original URL parsing in `res.location`
|
||||
* deps: connect@2.25.4
|
||||
- Fix `query` middleware breaking with argument
|
||||
- deps: body-parser@~1.6.3
|
||||
- deps: compression@~1.0.11
|
||||
- deps: connect-timeout@~1.2.2
|
||||
- deps: express-session@~1.7.5
|
||||
- deps: method-override@~2.1.3
|
||||
- deps: on-headers@~1.0.0
|
||||
- deps: parseurl@~1.3.0
|
||||
- deps: qs@1.2.1
|
||||
- deps: response-time@~2.0.1
|
||||
- deps: serve-index@~1.1.6
|
||||
- deps: serve-static@~1.5.1
|
||||
* deps: parseurl@~1.3.0
|
||||
|
||||
3.16.3 / 2014-08-07
|
||||
===================
|
||||
|
||||
* deps: connect@2.25.3
|
||||
- deps: multiparty@3.3.2
|
||||
|
||||
3.16.2 / 2014-08-07
|
||||
===================
|
||||
|
||||
* deps: connect@2.25.2
|
||||
- deps: body-parser@~1.6.2
|
||||
- deps: qs@1.2.0
|
||||
|
||||
3.16.1 / 2014-08-06
|
||||
===================
|
||||
|
||||
* deps: connect@2.25.1
|
||||
- deps: body-parser@~1.6.1
|
||||
- deps: qs@1.1.0
|
||||
|
||||
3.16.0 / 2014-08-05
|
||||
===================
|
||||
|
||||
* deps: connect@2.25.0
|
||||
- deps: body-parser@~1.6.0
|
||||
- deps: compression@~1.0.10
|
||||
- deps: csurf@~1.4.0
|
||||
- deps: express-session@~1.7.4
|
||||
- deps: qs@1.0.2
|
||||
- deps: serve-static@~1.5.0
|
||||
* deps: send@0.8.1
|
||||
- Add `extensions` option
|
||||
|
||||
3.15.3 / 2014-08-04
|
||||
===================
|
||||
|
||||
* fix `res.sendfile` regression for serving directory index files
|
||||
* deps: connect@2.24.3
|
||||
- deps: serve-index@~1.1.5
|
||||
- deps: serve-static@~1.4.4
|
||||
* deps: send@0.7.4
|
||||
- Fix incorrect 403 on Windows and Node.js 0.11
|
||||
- Fix serving index files without root dir
|
||||
|
||||
3.15.2 / 2014-07-27
|
||||
===================
|
||||
|
||||
* deps: connect@2.24.2
|
||||
- deps: body-parser@~1.5.2
|
||||
- deps: depd@0.4.4
|
||||
- deps: express-session@~1.7.2
|
||||
- deps: morgan@~1.2.2
|
||||
- deps: serve-static@~1.4.2
|
||||
* deps: depd@0.4.4
|
||||
- Work-around v8 generating empty stack traces
|
||||
* deps: send@0.7.2
|
||||
- deps: depd@0.4.4
|
||||
|
||||
3.15.1 / 2014-07-26
|
||||
===================
|
||||
|
||||
* deps: connect@2.24.1
|
||||
- deps: body-parser@~1.5.1
|
||||
- deps: depd@0.4.3
|
||||
- deps: express-session@~1.7.1
|
||||
- deps: morgan@~1.2.1
|
||||
- deps: serve-index@~1.1.4
|
||||
- deps: serve-static@~1.4.1
|
||||
* deps: depd@0.4.3
|
||||
- Fix exception when global `Error.stackTraceLimit` is too low
|
||||
* deps: send@0.7.1
|
||||
- deps: depd@0.4.3
|
||||
|
||||
3.15.0 / 2014-07-22
|
||||
===================
|
||||
|
||||
* Fix `req.protocol` for proxy-direct connections
|
||||
* Pass options from `res.sendfile` to `send`
|
||||
* deps: connect@2.24.0
|
||||
- deps: body-parser@~1.5.0
|
||||
- deps: compression@~1.0.9
|
||||
- deps: connect-timeout@~1.2.1
|
||||
- deps: debug@1.0.4
|
||||
- deps: depd@0.4.2
|
||||
- deps: express-session@~1.7.0
|
||||
- deps: finalhandler@0.1.0
|
||||
- deps: method-override@~2.1.2
|
||||
- deps: morgan@~1.2.0
|
||||
- deps: multiparty@3.3.1
|
||||
- deps: parseurl@~1.2.0
|
||||
- deps: serve-static@~1.4.0
|
||||
* deps: debug@1.0.4
|
||||
* deps: depd@0.4.2
|
||||
- Add `TRACE_DEPRECATION` environment variable
|
||||
- Remove non-standard grey color from color output
|
||||
- Support `--no-deprecation` argument
|
||||
- Support `--trace-deprecation` argument
|
||||
* deps: parseurl@~1.2.0
|
||||
- Cache URLs based on original value
|
||||
- Remove no-longer-needed URL mis-parse work-around
|
||||
- Simplify the "fast-path" `RegExp`
|
||||
* deps: send@0.7.0
|
||||
- Add `dotfiles` option
|
||||
- Cap `maxAge` value to 1 year
|
||||
- deps: debug@1.0.4
|
||||
- deps: depd@0.4.2
|
||||
|
||||
3.14.0 / 2014-07-11
|
||||
===================
|
||||
|
||||
* add explicit "Rosetta Flash JSONP abuse" protection
|
||||
- previous versions are not vulnerable; this is just explicit protection
|
||||
* deprecate `res.redirect(url, status)` -- use `res.redirect(status, url)` instead
|
||||
* fix `res.send(status, num)` to send `num` as json (not error)
|
||||
* remove unnecessary escaping when `res.jsonp` returns JSON response
|
||||
* deps: basic-auth@1.0.0
|
||||
- support empty password
|
||||
- support empty username
|
||||
* deps: connect@2.23.0
|
||||
- deps: debug@1.0.3
|
||||
- deps: express-session@~1.6.4
|
||||
- deps: method-override@~2.1.0
|
||||
- deps: parseurl@~1.1.3
|
||||
- deps: serve-static@~1.3.1
|
||||
* deps: debug@1.0.3
|
||||
- Add support for multiple wildcards in namespaces
|
||||
* deps: methods@1.1.0
|
||||
- add `CONNECT`
|
||||
* deps: parseurl@~1.1.3
|
||||
- faster parsing of href-only URLs
|
||||
|
||||
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` npm module instead
|
||||
- deprecate `verify` option to `urlencoded` -- use `body-parser` npm module instead
|
||||
- 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
|
||||
===================
|
||||
|
||||
* deps: connect@2.19.6
|
||||
- deps: body-parser@1.3.1
|
||||
- deps: compression@1.0.7
|
||||
- deps: debug@1.0.2
|
||||
- deps: serve-index@1.1.1
|
||||
- deps: serve-static@1.2.3
|
||||
* deps: debug@1.0.2
|
||||
* 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
|
||||
|
||||
3.10.4 / 2014-06-09
|
||||
===================
|
||||
|
||||
* deps: connect@2.19.5
|
||||
- fix "event emitter leak" warnings
|
||||
- deps: csurf@1.2.1
|
||||
- deps: debug@1.0.1
|
||||
- deps: serve-static@1.2.2
|
||||
- deps: type-is@1.2.1
|
||||
* deps: debug@1.0.1
|
||||
* deps: send@0.4.2
|
||||
- fix "event emitter leak" warnings
|
||||
- deps: finished@1.2.1
|
||||
- deps: debug@1.0.1
|
||||
|
||||
3.10.3 / 2014-06-05
|
||||
===================
|
||||
|
||||
* use `vary` module for `res.vary`
|
||||
* deps: connect@2.19.4
|
||||
- deps: errorhandler@1.0.2
|
||||
- deps: method-override@2.0.2
|
||||
- deps: serve-favicon@2.0.1
|
||||
* deps: debug@1.0.0
|
||||
|
||||
3.10.2 / 2014-06-03
|
||||
===================
|
||||
|
||||
* deps: connect@2.19.3
|
||||
- deps: compression@1.0.6
|
||||
|
||||
3.10.1 / 2014-06-03
|
||||
===================
|
||||
|
||||
* deps: connect@2.19.2
|
||||
- deps: compression@1.0.4
|
||||
* deps: proxy-addr@1.0.1
|
||||
|
||||
3.10.0 / 2014-06-02
|
||||
===================
|
||||
|
||||
* deps: connect@2.19.1
|
||||
- deprecate `methodOverride()` -- use `method-override` module directly
|
||||
- deprecate `methodOverride()` -- use `method-override` npm module instead
|
||||
- deps: body-parser@1.3.0
|
||||
- deps: method-override@2.0.1
|
||||
- deps: multiparty@3.2.8
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
Fast, unopinionated, minimalist web framework for [node](http://nodejs.org).
|
||||
|
||||
[](http://badge.fury.io/js/express) [](https://travis-ci.org/visionmedia/express) [](https://coveralls.io/r/visionmedia/express) [](https://www.gittip.com/visionmedia/)
|
||||
[](http://badge.fury.io/js/express)
|
||||
[](https://travis-ci.org/visionmedia/express)
|
||||
[](https://coveralls.io/r/visionmedia/express)
|
||||
[](https://www.gittip.com/dougwilson/)
|
||||
|
||||
```js
|
||||
var express = require('express');
|
||||
|
||||
@@ -335,7 +335,7 @@ function createApplicationAt(path) {
|
||||
|
||||
// Session support
|
||||
app = app.replace('{sess}', program.sessions
|
||||
? eol + 'app.use(express.cookieParser(\'your secret here\'));' + eol + 'app.use(express.session());'
|
||||
? eol + 'app.use(express.session({ secret: \'your secret here\' }));'
|
||||
: '');
|
||||
|
||||
// Template support
|
||||
|
||||
@@ -14,9 +14,8 @@ app.set('views', __dirname + '/views');
|
||||
|
||||
// middleware
|
||||
|
||||
app.use(express.bodyParser());
|
||||
app.use(express.cookieParser('shhhh, very secret'));
|
||||
app.use(express.session());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
app.use(express.session({ secret: 'shhhh, very secret' }));
|
||||
|
||||
// Session-persisted message middleware
|
||||
|
||||
|
||||
@@ -31,11 +31,10 @@ if (!module.parent) app.use(express.logger('dev'));
|
||||
app.use(express.static(__dirname + '/public'));
|
||||
|
||||
// session support
|
||||
app.use(express.cookieParser('some secret here'));
|
||||
app.use(express.session());
|
||||
app.use(express.session({ secret: 'some secret here' }));
|
||||
|
||||
// parse request bodies (req.body)
|
||||
app.use(express.bodyParser());
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
|
||||
// support _method (PUT in forms etc)
|
||||
app.use(express.methodOverride());
|
||||
|
||||
@@ -9,13 +9,8 @@ var app = express();
|
||||
|
||||
app.use(express.logger('dev'));
|
||||
|
||||
// Required by session() middleware
|
||||
// pass the secret for signed cookies
|
||||
// (required by session())
|
||||
app.use(express.cookieParser('keyboard cat'));
|
||||
|
||||
// Populates req.session
|
||||
app.use(express.session());
|
||||
app.use(express.session({ secret: 'keyboard cat' }));
|
||||
|
||||
app.get('/', function(req, res){
|
||||
var body = '';
|
||||
|
||||
@@ -10,13 +10,8 @@ var app = express();
|
||||
|
||||
app.use(express.logger('dev'));
|
||||
|
||||
// Required by session() middleware
|
||||
// pass the secret for signed cookies
|
||||
// (required by session())
|
||||
app.use(express.cookieParser('keyboard cat'));
|
||||
|
||||
// Populates req.session
|
||||
app.use(express.session({ store: new RedisStore }));
|
||||
app.use(express.session({ store: new RedisStore, secret: 'keyboard cat' }));
|
||||
|
||||
app.get('/', function(req, res){
|
||||
var body = '';
|
||||
|
||||
@@ -12,8 +12,8 @@ var connect = require('connect')
|
||||
, compileTrust = require('./utils').compileTrust
|
||||
, View = require('./view')
|
||||
, utils = connect.utils
|
||||
, deprecate = require('./utils').deprecate
|
||||
, http = require('http');
|
||||
var deprecate = require('depd')('express');
|
||||
|
||||
/**
|
||||
* Application prototype.
|
||||
@@ -48,10 +48,12 @@ app.defaultConfiguration = function(){
|
||||
// default settings
|
||||
this.enable('x-powered-by');
|
||||
this.set('etag', 'weak');
|
||||
this.set('env', process.env.NODE_ENV || 'development');
|
||||
var env = process.env.NODE_ENV || 'development';
|
||||
this.set('env', env);
|
||||
this.set('subdomain offset', 2);
|
||||
this.set('trust proxy', false);
|
||||
debug('booting in %s mode', this.get('env'));
|
||||
|
||||
debug('booting in %s mode', env);
|
||||
|
||||
// implicit middleware
|
||||
this.use(connect.query());
|
||||
@@ -86,13 +88,13 @@ app.defaultConfiguration = function(){
|
||||
this.set('views', process.cwd() + '/views');
|
||||
this.set('jsonp callback name', 'callback');
|
||||
|
||||
this.configure('development', function(){
|
||||
if (env === 'development') {
|
||||
this.set('json spaces', 2);
|
||||
});
|
||||
}
|
||||
|
||||
this.configure('production', function(){
|
||||
if (env === 'production') {
|
||||
this.enable('view cache');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -411,6 +413,9 @@ app.configure = function(env, fn){
|
||||
return this;
|
||||
};
|
||||
|
||||
app.configure = deprecate.function(app.configure,
|
||||
'app.configure: Check app.get(\'env\') in an if statement');
|
||||
|
||||
/**
|
||||
* Delegate `.VERB(...)` calls to `router.VERB(...)`.
|
||||
*/
|
||||
@@ -448,7 +453,7 @@ app.all = function(path){
|
||||
|
||||
// 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`
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var deprecate = require('depd')('express');
|
||||
var merge = require('merge-descriptors');
|
||||
var connect = require('connect')
|
||||
, proto = require('./application')
|
||||
@@ -9,7 +10,6 @@ var connect = require('connect')
|
||||
, Router = require('./router')
|
||||
, req = require('./request')
|
||||
, res = require('./response')
|
||||
, deprecate = require('./utils').deprecate
|
||||
, utils = connect.utils;
|
||||
|
||||
/**
|
||||
@@ -51,7 +51,7 @@ merge(exports, connect.middleware);
|
||||
* Deprecated createServer().
|
||||
*/
|
||||
|
||||
exports.createServer = deprecate(createApplication,
|
||||
exports.createServer = deprecate.function(createApplication,
|
||||
'createServer() is deprecated\n' +
|
||||
'express applications no longer inherit from http.Server\n' +
|
||||
'please use:\n' +
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var auth = require('basic-auth');
|
||||
var deprecate = require('depd')('express');
|
||||
var http = require('http')
|
||||
, utils = require('./utils')
|
||||
, connect = require('connect')
|
||||
@@ -339,7 +341,9 @@ req.is = function(type){
|
||||
* Return the protocol string "http" or "https"
|
||||
* when requested with TLS. When the "trust proxy"
|
||||
* setting trusts the socket address, the
|
||||
* "X-Forwarded-Proto" header field will be trusted.
|
||||
* "X-Forwarded-Proto" header field will be trusted
|
||||
* and used if present.
|
||||
*
|
||||
* If you're running behind a reverse proxy that
|
||||
* supplies https for you this may be enabled.
|
||||
*
|
||||
@@ -348,17 +352,18 @@ req.is = function(type){
|
||||
*/
|
||||
|
||||
req.__defineGetter__('protocol', function(){
|
||||
var proto = this.connection.encrypted
|
||||
? 'https'
|
||||
: 'http';
|
||||
var trust = this.app.get('trust proxy fn');
|
||||
|
||||
if (!trust(this.connection.remoteAddress)) {
|
||||
return this.connection.encrypted
|
||||
? 'https'
|
||||
: 'http';
|
||||
return proto;
|
||||
}
|
||||
|
||||
// Note: X-Forwarded-Proto is normally only ever a
|
||||
// single value, but this is to be safe.
|
||||
var proto = this.get('X-Forwarded-Proto') || 'http';
|
||||
proto = this.get('X-Forwarded-Proto') || proto;
|
||||
return proto.split(/\s*,\s*/)[0];
|
||||
});
|
||||
|
||||
@@ -422,20 +427,13 @@ req.__defineGetter__('ips', function(){
|
||||
*/
|
||||
|
||||
req.__defineGetter__('auth', function(){
|
||||
// missing
|
||||
var auth = this.get('Authorization');
|
||||
if (!auth) return;
|
||||
|
||||
// malformed
|
||||
var parts = auth.split(' ');
|
||||
if ('basic' != parts[0].toLowerCase()) return;
|
||||
if (!parts[1]) return;
|
||||
auth = parts[1];
|
||||
deprecate('req.auth: Use basic-auth npm module instead');
|
||||
|
||||
// credentials
|
||||
auth = new Buffer(auth, 'base64').toString().match(/^([^:]*):(.*)$/);
|
||||
if (!auth) return;
|
||||
return { username: auth[1], password: auth[2] };
|
||||
var creds = auth(this);
|
||||
if (!creds) return;
|
||||
|
||||
return { username: creds.name, password: creds.pass };
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
118
lib/response.js
118
lib/response.js
@@ -2,7 +2,10 @@
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var deprecate = require('depd')('express');
|
||||
var escapeHtml = require('escape-html');
|
||||
var parseUrl = require('parseurl');
|
||||
var vary = require('vary');
|
||||
var http = require('http')
|
||||
, path = require('path')
|
||||
, connect = require('connect')
|
||||
@@ -11,7 +14,6 @@ var http = require('http')
|
||||
, normalizeType = require('./utils').normalizeType
|
||||
, normalizeTypes = require('./utils').normalizeTypes
|
||||
, setCharset = require('./utils').setCharset
|
||||
, deprecate = require('./utils').deprecate
|
||||
, statusCodes = http.STATUS_CODES
|
||||
, cookie = require('cookie')
|
||||
, send = require('send')
|
||||
@@ -102,13 +104,15 @@ res.send = function(body){
|
||||
}
|
||||
}
|
||||
|
||||
// disambiguate res.send(status) and res.send(status, num)
|
||||
if (typeof body === 'number' && arguments.length === 1) {
|
||||
// res.send(status) will set status message as text string
|
||||
this.get('Content-Type') || this.type('txt');
|
||||
this.statusCode = body;
|
||||
body = http.STATUS_CODES[body];
|
||||
}
|
||||
|
||||
switch (typeof body) {
|
||||
// response status
|
||||
case 'number':
|
||||
this.get('Content-Type') || this.type('txt');
|
||||
this.statusCode = body;
|
||||
body = http.STATUS_CODES[body];
|
||||
break;
|
||||
// string defaulting to html
|
||||
case 'string':
|
||||
if (!this.get('Content-Type')) {
|
||||
@@ -117,6 +121,7 @@ res.send = function(body){
|
||||
}
|
||||
break;
|
||||
case 'boolean':
|
||||
case 'number':
|
||||
case 'object':
|
||||
if (null == body) {
|
||||
body = '';
|
||||
@@ -195,9 +200,11 @@ res.json = function(obj){
|
||||
// res.json(body, status) backwards compat
|
||||
if ('number' == typeof arguments[1]) {
|
||||
this.statusCode = arguments[1];
|
||||
return 'number' === typeof obj
|
||||
? jsonNumDeprecated.call(this, obj)
|
||||
: jsonDeprecated.call(this, obj);
|
||||
if (typeof obj === 'number') {
|
||||
deprecate('res.json(obj, status): Use res.json(status, obj) instead');
|
||||
} else {
|
||||
deprecate('res.json(num, status): Use res.status(status).json(num) instead');
|
||||
}
|
||||
} else {
|
||||
this.statusCode = obj;
|
||||
obj = arguments[1];
|
||||
@@ -217,12 +224,6 @@ res.json = function(obj){
|
||||
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.
|
||||
*
|
||||
@@ -245,9 +246,11 @@ res.jsonp = function(obj){
|
||||
// res.json(body, status) backwards compat
|
||||
if ('number' == typeof arguments[1]) {
|
||||
this.statusCode = arguments[1];
|
||||
return 'number' === typeof obj
|
||||
? jsonpNumDeprecated.call(this, obj)
|
||||
: jsonpDeprecated.call(this, obj);
|
||||
if (typeof obj === 'number') {
|
||||
deprecate('res.jsonp(obj, status): Use res.jsonp(status, obj) instead');
|
||||
} else {
|
||||
deprecate('res.jsonp(num, status): Use res.status(status).jsonp(num) instead');
|
||||
}
|
||||
} else {
|
||||
this.statusCode = obj;
|
||||
obj = arguments[1];
|
||||
@@ -258,14 +261,15 @@ res.jsonp = function(obj){
|
||||
var app = this.app;
|
||||
var replacer = app.get('json replacer');
|
||||
var spaces = app.get('json spaces');
|
||||
var body = JSON.stringify(obj, replacer, spaces)
|
||||
.replace(/\u2028/g, '\\u2028')
|
||||
.replace(/\u2029/g, '\\u2029');
|
||||
var body = JSON.stringify(obj, replacer, spaces);
|
||||
var callback = this.req.query[app.get('jsonp callback name')];
|
||||
|
||||
// content-type
|
||||
this.charset = this.charset || 'utf-8';
|
||||
this.get('Content-Type') || this.set('Content-Type', 'application/json');
|
||||
if (!this.get('Content-Type')) {
|
||||
this.charset = 'utf-8';
|
||||
this.set('X-Content-Type-Options', 'nosniff');
|
||||
this.set('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
// fixup callback
|
||||
if (Array.isArray(callback)) {
|
||||
@@ -273,21 +277,27 @@ res.jsonp = function(obj){
|
||||
}
|
||||
|
||||
// jsonp
|
||||
if (callback && 'string' === typeof callback) {
|
||||
if (typeof callback === 'string' && callback.length !== 0) {
|
||||
this.charset = 'utf-8';
|
||||
this.set('X-Content-Type-Options', 'nosniff');
|
||||
this.set('Content-Type', 'text/javascript');
|
||||
var cb = callback.replace(/[^\[\]\w$.]/g, '');
|
||||
body = 'typeof ' + cb + ' === \'function\' && ' + cb + '(' + body + ');';
|
||||
|
||||
// restrict callback charset
|
||||
callback = callback.replace(/[^\[\]\w$.]/g, '');
|
||||
|
||||
// replace chars not allowed in JavaScript that are in JSON
|
||||
body = body
|
||||
.replace(/\u2028/g, '\\u2028')
|
||||
.replace(/\u2029/g, '\\u2029');
|
||||
|
||||
// the /**/ is a specific security mitigation for "Rosetta Flash JSONP abuse"
|
||||
// the typeof check is just to reduce client error noise
|
||||
body = '/**/ typeof ' + callback + ' === \'function\' && ' + callback + '(' + 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`.
|
||||
*
|
||||
@@ -299,8 +309,11 @@ var jsonpNumDeprecated = deprecate(res.json,
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `maxAge` defaulting to 0
|
||||
* - `root` root directory for relative filenames
|
||||
* - `maxAge` defaulting to 0
|
||||
* - `root` root directory for relative filenames
|
||||
* - `dotfiles` serve dotfiles, defaulting to false; can be `"allow"` to send them
|
||||
*
|
||||
* Other options are passed along to `send`.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
@@ -376,9 +389,7 @@ res.sendfile = function(path, options, fn){
|
||||
}
|
||||
|
||||
// transfer
|
||||
var file = send(req, path);
|
||||
if (options.root) file.root(options.root);
|
||||
file.maxage(options.maxAge || 0);
|
||||
var file = send(req, path, options);
|
||||
file.on('error', error);
|
||||
file.on('directory', next);
|
||||
file.on('stream', stream);
|
||||
@@ -683,7 +694,7 @@ res.location = function(url){
|
||||
if (!~url.indexOf('://') && 0 != url.indexOf('//')) {
|
||||
// relative to path
|
||||
if ('.' == url[0]) {
|
||||
path = req.originalUrl.split('?')[0];
|
||||
path = parseUrl.original(req).pathname;
|
||||
path = path + ('/' == path[path.length - 1] ? '' : '/');
|
||||
url = resolve(path, url);
|
||||
// relative to mount-point
|
||||
@@ -711,11 +722,8 @@ res.location = function(url){
|
||||
* res.redirect('/foo/bar');
|
||||
* res.redirect('http://example.com');
|
||||
* res.redirect(301, 'http://example.com');
|
||||
* res.redirect('http://example.com', 301);
|
||||
* res.redirect('../login'); // /blog/post/1 -> /blog/login
|
||||
*
|
||||
* @param {String} url
|
||||
* @param {Number} code
|
||||
* @api public
|
||||
*/
|
||||
|
||||
@@ -730,6 +738,7 @@ res.redirect = function(url){
|
||||
status = url;
|
||||
url = arguments[1];
|
||||
} else {
|
||||
deprecate('res.redirect(ur, status): Use res.redirect(status, url) instead');
|
||||
status = arguments[1];
|
||||
}
|
||||
}
|
||||
@@ -770,31 +779,12 @@ res.redirect = function(url){
|
||||
*/
|
||||
|
||||
res.vary = function(field){
|
||||
var self = this;
|
||||
|
||||
// nothing
|
||||
// checks for back-compat
|
||||
if (!field) return this;
|
||||
if (Array.isArray(field) && !field.length) return this;
|
||||
|
||||
// array
|
||||
if (Array.isArray(field)) {
|
||||
field.forEach(function(field){
|
||||
self.vary(field);
|
||||
});
|
||||
return;
|
||||
}
|
||||
vary(this, field);
|
||||
|
||||
var vary = this.get('Vary');
|
||||
|
||||
// append
|
||||
if (vary) {
|
||||
vary = vary.split(/ *, */);
|
||||
if (!~vary.indexOf(field)) vary.push(field);
|
||||
this.set('Vary', vary.join(', '));
|
||||
return this;
|
||||
}
|
||||
|
||||
// set
|
||||
this.set('Vary', field);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
52
lib/utils.js
52
lib/utils.js
@@ -4,10 +4,10 @@
|
||||
*/
|
||||
|
||||
var mime = require('connect').mime
|
||||
, deprecate = require('util').deprecate
|
||||
, proxyaddr = require('proxy-addr')
|
||||
, crc32 = require('buffer-crc32')
|
||||
, crypto = require('crypto');
|
||||
var typer = require('media-typer');
|
||||
|
||||
/**
|
||||
* toString ref.
|
||||
@@ -15,35 +15,6 @@ var mime = require('connect').mime
|
||||
|
||||
var toString = {}.toString;
|
||||
|
||||
/**
|
||||
* 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`.
|
||||
*
|
||||
@@ -436,21 +407,12 @@ exports.compileTrust = function(val) {
|
||||
exports.setCharset = function(type, charset){
|
||||
if (!type || !charset) return type;
|
||||
|
||||
var exists = charsetRegExp.test(type);
|
||||
// parse type
|
||||
var parsed = typer.parse(type);
|
||||
|
||||
// removing existing charset
|
||||
if (exists) {
|
||||
var parts = type.split(';');
|
||||
// set charset
|
||||
parsed.parameters.charset = charset;
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
68
package.json
68
package.json
@@ -1,37 +1,15 @@
|
||||
{
|
||||
"name": "express",
|
||||
"description": "Sinatra inspired web development framework",
|
||||
"version": "3.10.0",
|
||||
"version": "3.16.4",
|
||||
"author": "TJ Holowaychuk <tj@vision-media.ca>",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "TJ Holowaychuk",
|
||||
"email": "tj@vision-media.ca"
|
||||
},
|
||||
{
|
||||
"name": "Aaron Heckmann",
|
||||
"email": "aaron.heckmann+github@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Ciaran Jessup",
|
||||
"email": "ciaranj@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Douglas Christopher Wilson",
|
||||
"email": "doug@somethingdoug.com"
|
||||
},
|
||||
{
|
||||
"name": "Guillermo Rauch",
|
||||
"email": "rauchg@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Ong",
|
||||
"email": "me@jongleberry.com"
|
||||
},
|
||||
{
|
||||
"name": "Roman Shtylman",
|
||||
"email": "shtylman+expressjs@gmail.com"
|
||||
}
|
||||
"Aaron Heckmann <aaron.heckmann+github@gmail.com>",
|
||||
"Ciaran Jessup <ciaranj@gmail.com>",
|
||||
"Douglas Christopher Wilson <doug@somethingdoug.com>",
|
||||
"Guillermo Rauch <rauchg@gmail.com>",
|
||||
"Jonathan Ong <me@jongleberry.com>",
|
||||
"Roman Shtylman <shtylman+expressjs@gmail.com"
|
||||
],
|
||||
"keywords": [
|
||||
"express",
|
||||
@@ -44,34 +22,38 @@
|
||||
"app",
|
||||
"api"
|
||||
],
|
||||
"repository": "git://github.com/visionmedia/express",
|
||||
"repository": "visionmedia/express",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer-crc32": "0.2.1",
|
||||
"connect": "2.19.1",
|
||||
"basic-auth": "1.0.0",
|
||||
"buffer-crc32": "0.2.3",
|
||||
"connect": "2.25.4",
|
||||
"commander": "1.3.2",
|
||||
"debug": "1.0.4",
|
||||
"depd": "0.4.4",
|
||||
"escape-html": "1.0.1",
|
||||
"methods": "1.0.1",
|
||||
"media-typer": "0.2.0",
|
||||
"methods": "1.1.0",
|
||||
"mkdirp": "0.5.0",
|
||||
"parseurl": "1.0.1",
|
||||
"proxy-addr": "1.0.0",
|
||||
"parseurl": "~1.3.0",
|
||||
"proxy-addr": "1.0.1",
|
||||
"range-parser": "1.0.0",
|
||||
"send": "0.4.1",
|
||||
"send": "0.8.1",
|
||||
"vary": "0.1.0",
|
||||
"cookie": "0.1.2",
|
||||
"fresh": "0.2.2",
|
||||
"cookie-signature": "1.0.3",
|
||||
"merge-descriptors": "0.0.2",
|
||||
"debug": ">= 0.8.0 < 1"
|
||||
"cookie-signature": "1.0.4",
|
||||
"merge-descriptors": "0.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"istanbul": "0.2.10",
|
||||
"mocha": "~1.20.0",
|
||||
"connect-redis": "~1.5.0",
|
||||
"istanbul": "0.3.0",
|
||||
"mocha": "~1.21.4",
|
||||
"should": "~4.0.0",
|
||||
"ejs": "~1.0.0",
|
||||
"jade": "~1.3.1",
|
||||
"jade": "~1.5.0",
|
||||
"hjs": "~0.0.6",
|
||||
"marked": "0.3.2",
|
||||
"connect-redis": "~1.4.5",
|
||||
"supertest": "~0.13.0"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -33,6 +33,7 @@ describe('mvc', function(){
|
||||
it('should update the pet', function(done){
|
||||
request(app)
|
||||
.put('/pet/3')
|
||||
.set('Content-Type', 'application/x-www-form-urlencoded')
|
||||
.send({ pet: { name: 'Boots' } })
|
||||
.end(function(err, res){
|
||||
if (err) return done(err);
|
||||
@@ -95,6 +96,7 @@ describe('mvc', function(){
|
||||
it('should update the user', function(done){
|
||||
request(app)
|
||||
.put('/user/1')
|
||||
.set('Content-Type', 'application/x-www-form-urlencoded')
|
||||
.send({ user: { name: 'Tobo' }})
|
||||
.end(function(err, res){
|
||||
if (err) return done(err);
|
||||
@@ -109,6 +111,7 @@ describe('mvc', function(){
|
||||
it('should create a pet for user', function(done){
|
||||
request(app)
|
||||
.post('/user/2/pet')
|
||||
.set('Content-Type', 'application/x-www-form-urlencoded')
|
||||
.send({ pet: { name: 'Snickers' }})
|
||||
.expect('Location', '/user/2')
|
||||
.expect(302, function(err, res){
|
||||
|
||||
@@ -34,6 +34,8 @@ describe('HEAD', function(){
|
||||
.get('/tobi')
|
||||
.expect(200, function(err, res){
|
||||
if (err) return done(err);
|
||||
delete headers.date;
|
||||
delete res.headers.date;
|
||||
assert.deepEqual(res.headers, headers);
|
||||
done();
|
||||
});
|
||||
|
||||
1
test/fixtures/.name
vendored
Normal file
1
test/fixtures/.name
vendored
Normal file
@@ -0,0 +1 @@
|
||||
tobi
|
||||
1
test/fixtures/blog/index.html
vendored
Normal file
1
test/fixtures/blog/index.html
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<b>index</b>
|
||||
@@ -32,6 +32,21 @@ describe('req', function(){
|
||||
.expect('https', done);
|
||||
})
|
||||
|
||||
it('should default to the socket addr if X-Forwarded-Proto not present', function(done){
|
||||
var app = express();
|
||||
|
||||
app.enable('trust proxy');
|
||||
|
||||
app.use(function(req, res){
|
||||
req.connection.encrypted = true;
|
||||
res.end(req.protocol);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('https', done);
|
||||
})
|
||||
|
||||
it('should ignore X-Forwarded-Proto if socket addr not trusted', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
@@ -14,11 +14,8 @@ describe('res', function(){
|
||||
|
||||
request(app)
|
||||
.get('/?callback=something')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
|
||||
res.text.should.equal('typeof something === \'function\' && something({"count":1});');
|
||||
done();
|
||||
})
|
||||
.expect('Content-Type', 'text/javascript; charset=utf-8')
|
||||
.expect(200, /something\(\{"count":1\}\);/, done);
|
||||
})
|
||||
|
||||
it('should use first callback parameter with jsonp', function(done){
|
||||
@@ -29,12 +26,9 @@ describe('res', function(){
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/?callback=something&callback=somethingelse')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
|
||||
res.text.should.equal('typeof something === \'function\' && something({"count":1});');
|
||||
done();
|
||||
})
|
||||
.get('/?callback=something&callback=somethingelse')
|
||||
.expect('Content-Type', 'text/javascript; charset=utf-8')
|
||||
.expect(200, /something\(\{"count":1\}\);/, done);
|
||||
})
|
||||
|
||||
it('should ignore object callback parameter with jsonp', function(done){
|
||||
@@ -61,11 +55,8 @@ describe('res', function(){
|
||||
|
||||
request(app)
|
||||
.get('/?clb=something')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
|
||||
res.text.should.equal('typeof something === \'function\' && something({"count":1});');
|
||||
done();
|
||||
})
|
||||
.expect('Content-Type', 'text/javascript; charset=utf-8')
|
||||
.expect(200, /something\(\{"count":1\}\);/, done);
|
||||
})
|
||||
|
||||
it('should allow []', function(done){
|
||||
@@ -77,11 +68,8 @@ describe('res', function(){
|
||||
|
||||
request(app)
|
||||
.get('/?callback=callbacks[123]')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
|
||||
res.text.should.equal('typeof callbacks[123] === \'function\' && callbacks[123]({"count":1});');
|
||||
done();
|
||||
})
|
||||
.expect('Content-Type', 'text/javascript; charset=utf-8')
|
||||
.expect(200, /callbacks\[123\]\(\{"count":1\}\);/, done);
|
||||
})
|
||||
|
||||
it('should disallow arbitrary js', function(done){
|
||||
@@ -93,11 +81,8 @@ describe('res', function(){
|
||||
|
||||
request(app)
|
||||
.get('/?callback=foo;bar()')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
|
||||
res.text.should.equal('typeof foobar === \'function\' && foobar({});');
|
||||
done();
|
||||
})
|
||||
.expect('Content-Type', 'text/javascript; charset=utf-8')
|
||||
.expect(200, /foobar\(\{\}\);/, done);
|
||||
})
|
||||
|
||||
it('should escape utf whitespace', function(done){
|
||||
@@ -109,13 +94,37 @@ describe('res', function(){
|
||||
|
||||
request(app)
|
||||
.get('/?callback=foo')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
|
||||
res.text.should.equal('typeof foo === \'function\' && foo({"str":"\\u2028 \\u2029 woot"});');
|
||||
done();
|
||||
});
|
||||
.expect('Content-Type', 'text/javascript; charset=utf-8')
|
||||
.expect(200, /foo\(\{"str":"\\u2028 \\u2029 woot"\}\);/, done);
|
||||
});
|
||||
|
||||
it('should not escape utf whitespace for json fallback', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.jsonp({ str: '\u2028 \u2029 woot' });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Content-Type', 'application/json; charset=utf-8')
|
||||
.expect(200, '{"str":"\u2028 \u2029 woot"}', done);
|
||||
});
|
||||
|
||||
it('should include security header and prologue', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.jsonp({ count: 1 });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/?callback=something')
|
||||
.expect('Content-Type', 'text/javascript; charset=utf-8')
|
||||
.expect('X-Content-Type-Options', 'nosniff')
|
||||
.expect(200, /^\/\*\*\//, done);
|
||||
})
|
||||
|
||||
it('should not override previous Content-Types with no callback', function(done){
|
||||
var app = express();
|
||||
|
||||
@@ -127,7 +136,11 @@ describe('res', function(){
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Content-Type', 'application/vnd.example+json; charset=utf-8')
|
||||
.expect(200, '{"hello":"world"}', done);
|
||||
.expect(200, '{"hello":"world"}', function (err, res) {
|
||||
if (err) return done(err);
|
||||
res.headers.should.not.have.property('x-content-type-options');
|
||||
done();
|
||||
});
|
||||
})
|
||||
|
||||
it('should override previous Content-Types with callback', function(done){
|
||||
@@ -141,6 +154,7 @@ describe('res', function(){
|
||||
request(app)
|
||||
.get('/?callback=cb')
|
||||
.expect('Content-Type', 'text/javascript; charset=utf-8')
|
||||
.expect('X-Content-Type-Options', 'nosniff')
|
||||
.expect(200, /cb\(\{"hello":"world"\}\);$/, done);
|
||||
})
|
||||
|
||||
|
||||
@@ -77,6 +77,21 @@ describe('res', function(){
|
||||
})
|
||||
})
|
||||
|
||||
describe('.send(code, number)', function(){
|
||||
it('should send number as json', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.send(200, 0.123);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Content-Type', 'application/json; charset=utf-8')
|
||||
.expect(200, '0.123', done);
|
||||
})
|
||||
})
|
||||
|
||||
describe('.send(String)', function(){
|
||||
it('should send as html', function(done){
|
||||
var app = express();
|
||||
|
||||
@@ -106,6 +106,54 @@ describe('res', function(){
|
||||
})
|
||||
|
||||
describe('.sendfile(path)', function(){
|
||||
it('should not serve dotfiles', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.sendfile('test/fixtures/.name');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect(404, done);
|
||||
})
|
||||
|
||||
it('should accept dotfiles option', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.sendfile('test/fixtures/.name', { dotfiles: 'allow' });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect(200, 'tobi', done);
|
||||
})
|
||||
|
||||
it('should transfer a file', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendfile('test/fixtures/name.txt');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect(200, 'tobi', done);
|
||||
});
|
||||
|
||||
it('should transfer a directory index file', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendfile('test/fixtures/blog/');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect(200, '<b>index</b>', done);
|
||||
});
|
||||
|
||||
describe('with an absolute path', function(){
|
||||
it('should transfer the file', function(done){
|
||||
var app = express();
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
|
||||
process.env.NODE_ENV = 'test';
|
||||
process.env.NO_DEPRECATION = 'connect,express';
|
||||
|
||||
@@ -2,28 +2,6 @@
|
||||
var utils = require('../lib/utils')
|
||||
, assert = require('assert');
|
||||
|
||||
describe('utils.deprecate(fn, msg)', function(){
|
||||
var env
|
||||
before(function(){
|
||||
env = process.env.NODE_ENV
|
||||
})
|
||||
after(function(){
|
||||
process.env.NODE_ENV = env
|
||||
})
|
||||
|
||||
it('should pass-through fn in test environment', function(){
|
||||
var fn = function(){}
|
||||
process.env.NODE_ENV = 'test'
|
||||
utils.deprecate(fn).should.equal(fn)
|
||||
})
|
||||
|
||||
it('should return new fn in other environment', function(){
|
||||
var fn = function(){}
|
||||
process.env.NODE_ENV = ''
|
||||
utils.deprecate(fn).should.not.equal(fn)
|
||||
})
|
||||
})
|
||||
|
||||
describe('utils.etag(body, encoding)', function(){
|
||||
it('should support strings', function(){
|
||||
utils.etag('express!')
|
||||
|
||||
Reference in New Issue
Block a user