Compare commits

...

13 Commits
3.6.0 ... 3.7.0

Author SHA1 Message Date
Douglas Christopher Wilson
b91cd66fc5 3.7.0 2014-05-18 10:40:13 -04:00
Douglas Christopher Wilson
787d630157 update should to 3.3.1 2014-05-18 10:38:42 -04:00
Douglas Christopher Wilson
1f938c560a tests: improve examples/auth tests 2014-05-18 01:54:05 -04:00
Douglas Christopher Wilson
a96924a555 build: remove lib-cov fork 2014-05-18 01:35:12 -04:00
Douglas Christopher Wilson
33dc6629ff update connect to 2.16.2 2014-05-18 01:30:44 -04:00
Douglas Christopher Wilson
1b3fb0af8c build: add coverage reporting 2014-05-18 01:25:15 -04:00
Douglas Christopher Wilson
12da523ff7 build: test coverage with istanbul 2014-05-18 01:23:15 -04:00
Douglas Christopher Wilson
0f49d80623 build: clean up package file 2014-05-18 01:16:38 -04:00
Douglas Christopher Wilson
1717516a78 build: improve platform portability 2014-05-18 01:14:45 -04:00
Jonathan Ong
328c6d3060 remove unnecessary test/support/http
backport of 643397ed21
2014-05-18 00:57:54 -04:00
Douglas Christopher Wilson
566720be15 improve proxy trust with ip address list
closes #2099
2014-05-17 20:02:20 -04:00
Douglas Christopher Wilson
65f13c3cc6 update connect to 2.16.1 2014-05-17 14:30:52 -04:00
Douglas Christopher Wilson
d98e2e7498 deprecation messages are bright red on TTYs 2014-05-13 17:06:45 -04:00
83 changed files with 482 additions and 255 deletions

5
.gitignore vendored
View File

@@ -1,6 +1,5 @@
coverage.html
coverage/
.DS_Store
lib-cov
*.seed
*.log
*.csv
@@ -13,7 +12,5 @@ benchmarks/graphs
testing
node_modules/
testing
.coverage_data
cover_html
test.js
.idea

View File

@@ -1,5 +1,6 @@
.git*
benchmarks/
coverage/
docs/
examples/
support/
@@ -7,5 +8,3 @@ test/
testing.js
.DS_Store
.travis.yml
coverage.html
lib-cov

View File

@@ -7,3 +7,4 @@ matrix:
allow_failures:
- node_js: "0.11"
fast_finish: true
script: "npm run-script test-travis"

View File

@@ -1,3 +1,26 @@
3.7.0 / 2014-05-18
==================
* proper proxy trust with `app.set('trust proxy', trust)`
- `app.set('trust proxy', 1)` trust first hop
- `app.set('trust proxy', 'loopback')` trust loopback addresses
- `app.set('trust proxy', '10.0.0.1')` trust single IP
- `app.set('trust proxy', '10.0.0.1/16')` trust subnet
- `app.set('trust proxy', '10.0.0.1, 10.0.0.2')` trust list
- `app.set('trust proxy', false)` turn off
- `app.set('trust proxy', true)` trust everything
* update connect to 2.16.2
- deprecate `res.headerSent` -- use `res.headersSent`
- deprecate `res.on("header")` -- use on-headers module instead
- fix edge-case in `res.appendHeader` that would append in wrong order
- json: use body-parser
- urlencoded: use body-parser
- dep: bytes@1.0.0
- dep: cookie-parser@1.1.0
- dep: csurf@1.2.0
- dep: express-session@1.1.0
- dep: method-override@1.0.1
3.6.0 / 2014-05-09
==================

View File

@@ -1,34 +0,0 @@
MOCHA_OPTS= --check-leaks
REPORTER = dot
check: test
test: test-unit test-acceptance
test-unit:
@NODE_ENV=test ./node_modules/.bin/mocha \
--reporter $(REPORTER) \
--globals setImmediate,clearImmediate \
$(MOCHA_OPTS)
test-acceptance:
@NODE_ENV=test ./node_modules/.bin/mocha \
--reporter $(REPORTER) \
--bail \
test/acceptance/*.js
test-cov: lib-cov
@EXPRESS_COV=1 $(MAKE) test REPORTER=html-cov > coverage.html
lib-cov:
@jscoverage lib lib-cov
bench:
@$(MAKE) -C benchmarks
clean:
rm -f coverage.html
rm -fr lib-cov
.PHONY: test test-unit test-acceptance bench clean

View File

@@ -2,7 +2,7 @@
Fast, unopinionated, minimalist web framework for [node](http://nodejs.org).
[![Build Status](https://travis-ci.org/visionmedia/express.svg?branch=master)](https://travis-ci.org/visionmedia/express) [![Gittip](http://img.shields.io/gittip/visionmedia.svg)](https://www.gittip.com/visionmedia/) [![NPM version](https://badge.fury.io/js/express.svg)](http://badge.fury.io/js/express)
[![NPM version](https://badge.fury.io/js/express.svg)](http://badge.fury.io/js/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) [![Gittip](http://img.shields.io/gittip/visionmedia.svg)](https://www.gittip.com/visionmedia/)
```js
var express = require('express');
@@ -94,7 +94,9 @@ To run the test suite, first invoke the following command within the repo, insta
Then run the tests:
$ make test
```sh
$ npm test
```
## Contributors

View File

@@ -1,4 +1,2 @@
module.exports = process.env.EXPRESS_COV
? require('./lib-cov/express')
: require('./lib/express');
module.exports = require('./lib/express');

View File

@@ -8,6 +8,7 @@ var connect = require('connect')
, middleware = require('./middleware')
, debug = require('debug')('express:application')
, locals = require('./utils').locals
, compileTrust = require('./utils').compileTrust
, View = require('./view')
, utils = connect.utils
, deprecate = require('./utils').deprecate
@@ -48,6 +49,7 @@ app.defaultConfiguration = function(){
this.enable('etag');
this.set('env', process.env.NODE_ENV || 'development');
this.set('subdomain offset', 2);
this.set('trust proxy', false);
debug('booting in %s mode', this.get('env'));
// implicit middleware
@@ -253,6 +255,12 @@ app.set = function(setting, val){
return this.settings[setting];
} else {
this.settings[setting] = val;
if (setting === 'trust proxy') {
debug('compile trust proxy %j', val);
this.set('trust proxy fn', compileTrust(val));
}
return this;
}
};

View File

@@ -8,7 +8,8 @@ var http = require('http')
, connect = require('connect')
, fresh = require('fresh')
, parseRange = require('range-parser')
, parse = connect.utils.parseUrl
, parse = require('parseurl')
, proxyaddr = require('proxy-addr')
, mime = connect.mime;
/**
@@ -337,19 +338,26 @@ req.is = function(type){
/**
* Return the protocol string "http" or "https"
* when requested with TLS. When the "trust proxy"
* setting is enabled the "X-Forwarded-Proto" header
* field will be trusted. If you're running behind
* a reverse proxy that supplies https for you this
* may be enabled.
* setting trusts the socket address, the
* "X-Forwarded-Proto" header field will be trusted.
* If you're running behind a reverse proxy that
* supplies https for you this may be enabled.
*
* @return {String}
* @api public
*/
req.__defineGetter__('protocol', function(){
var trustProxy = this.app.get('trust proxy');
if (this.connection.encrypted) return 'https';
if (!trustProxy) return 'http';
var trust = this.app.get('trust proxy fn');
if (!trust(this.connection.remoteAddress)) {
return this.connection.encrypted
? 'https'
: 'http';
}
// 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';
return proto.split(/\s*,\s*/)[0];
});
@@ -368,36 +376,36 @@ req.__defineGetter__('secure', function(){
});
/**
* Return the remote address, or when
* "trust proxy" is `true` return
* the upstream addr.
* Return the remote address from the trusted proxy.
*
* The is the remote address on the socket unless
* "trust proxy" is set.
*
* @return {String}
* @api public
*/
req.__defineGetter__('ip', function(){
return this.ips[0] || this.connection.remoteAddress;
var trust = this.app.get('trust proxy fn');
return proxyaddr(this, trust);
});
/**
* When "trust proxy" is `true`, parse
* the "X-Forwarded-For" ip address list.
* When "trust proxy" is set, trusted proxy addresses + client.
*
* For example if the value were "client, proxy1, proxy2"
* you would receive the array `["client", "proxy1", "proxy2"]`
* where "proxy2" is the furthest down-stream.
* where "proxy2" is the furthest down-stream and "proxy1" and
* "proxy2" were trusted.
*
* @return {Array}
* @api public
*/
req.__defineGetter__('ips', function(){
var trustProxy = this.app.get('trust proxy');
var val = this.get('X-Forwarded-For');
return trustProxy && val
? val.split(/ *, */)
: [];
var trust = this.app.get('trust proxy fn');
var addrs = proxyaddr.all(this, trust);
return addrs.slice(1).reverse();
});
/**
@@ -467,19 +475,30 @@ req.__defineGetter__('path', function(){
/**
* Parse the "Host" header field hostname.
*
* When the "trust proxy" setting trusts the socket
* address, the "X-Forwarded-Host" header field will
* be trusted.
*
* @return {String}
* @api public
*/
req.__defineGetter__('host', function(){
var trustProxy = this.app.get('trust proxy');
var host = trustProxy && this.get('X-Forwarded-Host');
host = host || this.get('Host');
var trust = this.app.get('trust proxy fn');
var host = this.get('X-Forwarded-Host');
if (!host || !trust(this.connection.remoteAddress)) {
host = this.get('Host');
}
if (!host) return;
// IPv6 literal support
var offset = host[0] === '['
? host.indexOf(']') + 1
: 0;
var index = host.indexOf(':', offset);
return ~index
? host.substring(0, index)
: host;

View File

@@ -334,13 +334,13 @@ res.sendfile = function(path, options, fn){
// clean up
cleanup();
if (!self.headerSent) self.removeHeader('Content-Disposition');
if (!self.headersSent) self.removeHeader('Content-Disposition');
// callback available
if (fn) return fn(err);
// list in limbo if there's no callback
if (self.headerSent) return;
if (self.headersSent) return;
// delegate
next(err);
@@ -375,7 +375,7 @@ res.sendfile = function(path, options, fn){
* Optionally providing an alternate attachment `filename`,
* and optional callback `fn(err)`. The callback is invoked
* when the data transfer is complete, or when an error has
* ocurred. Be sure to check `res.headerSent` if you plan to respond.
* ocurred. Be sure to check `res.headersSent` if you plan to respond.
*
* This method uses `res.sendfile()`.
*

View File

@@ -2,11 +2,11 @@
* Module dependencies.
*/
var Route = require('./route')
, utils = require('../utils')
, methods = require('methods')
, debug = require('debug')('express:router')
, parse = require('connect').utils.parseUrl;
var Route = require('./route');
var utils = require('../utils');
var methods = require('methods');
var debug = require('debug')('express:router');
var parseUrl = require('parseurl');
/**
* Expose `Router` constructor.
@@ -182,7 +182,7 @@ Router.prototype._dispatch = function(req, res, next){
*/
Router.prototype._options = function(req, res, next){
var path = parse(req).pathname
var path = parseUrl(req).pathname
, body = this._optionsFor(path).join(',');
if (!body) return next();
res.set('Allow', body).send(body);
@@ -222,7 +222,7 @@ Router.prototype._optionsFor = function(path){
Router.prototype.matchRequest = function(req, i, head){
var method = req.method.toLowerCase()
, url = parse(req)
, url = parseUrl(req)
, path = url.pathname
, routes = this.map
, i = i || 0

View File

@@ -5,6 +5,7 @@
var mime = require('connect').mime
, deprecate = require('util').deprecate
, proxyaddr = require('proxy-addr')
, crc32 = require('buffer-crc32');
/**
@@ -14,7 +15,8 @@ var mime = require('connect').mime
var toString = {}.toString;
/**
* Deprecate function, like core `util.deprecate`
* Deprecate function, like core `util.deprecate`,
* but with NODE_ENV and color support.
*
* @param {Function} fn
* @param {String} msg
@@ -23,9 +25,17 @@ var toString = {}.toString;
*/
exports.deprecate = function(fn, msg){
return 'test' !== process.env.NODE_ENV
? deprecate(fn, 'express: ' + msg)
: fn;
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);
};
/**
@@ -328,3 +338,32 @@ exports.pathRegexp = function(path, keys, sensitive, strict) {
.replace(/\*/g, '(.*)');
return new RegExp('^' + path + '$', sensitive ? '' : 'i');
}
/**
* Compile "proxy trust" value to function.
*
* @param {Boolean|String|Number|Array|Function} val
* @return {Function}
* @api private
*/
exports.compileTrust = function(val) {
if (typeof val === 'function') return val;
if (val === true) {
// Support plain true/false
return function(){ return true };
}
if (typeof val === 'number') {
// Support trusting hop count
return function(a, i){ return i < val };
}
if (typeof val === 'string') {
// Support comma-separated values
val = val.split(/ *, */);
}
return proxyaddr.compile(val || []);
}

View File

@@ -1,7 +1,7 @@
{
"name": "express",
"description": "Sinatra inspired web development framework",
"version": "3.6.0",
"version": "3.7.0",
"author": "TJ Holowaychuk <tj@vision-media.ca>",
"contributors": [
{
@@ -33,31 +33,6 @@
"email": "shtylman+expressjs@gmail.com"
}
],
"dependencies": {
"connect": "2.15.0",
"commander": "1.3.2",
"methods": "1.0.0",
"mkdirp": "0.5.0",
"range-parser": "1.0.0",
"cookie": "0.1.2",
"buffer-crc32": "0.2.1",
"fresh": "0.2.2",
"send": "0.3.0",
"cookie-signature": "1.0.3",
"merge-descriptors": "0.0.2",
"debug": ">= 0.8.0 < 1"
},
"devDependencies": {
"ejs": "~0.8.4",
"mocha": "~1.18.2",
"jade": "~0.30.0",
"hjs": "~0.0.6",
"stylus": "~0.40.0",
"should": "~2.1.1",
"connect-redis": "~1.4.5",
"marked": "0.2.10",
"supertest": "~0.12.1"
},
"keywords": [
"express",
"framework",
@@ -70,16 +45,46 @@
"api"
],
"repository": "git://github.com/visionmedia/express",
"main": "index",
"license": "MIT",
"dependencies": {
"connect": "2.16.2",
"commander": "1.3.2",
"methods": "1.0.0",
"mkdirp": "0.5.0",
"parseurl": "1.0.1",
"proxy-addr": "1.0.0",
"range-parser": "1.0.0",
"cookie": "0.1.2",
"buffer-crc32": "0.2.1",
"fresh": "0.2.2",
"send": "0.3.0",
"cookie-signature": "1.0.3",
"merge-descriptors": "0.0.2",
"debug": ">= 0.8.0 < 1"
},
"devDependencies": {
"coveralls": "2.10.0",
"ejs": "~0.8.4",
"istanbul": "0.2.10",
"mocha": "~1.18.2",
"should": "~3.3.1",
"jade": "~0.30.0",
"hjs": "~0.0.6",
"stylus": "~0.40.0",
"connect-redis": "~1.4.5",
"marked": "0.2.10",
"supertest": "~0.12.1"
},
"engines": {
"node": ">= 0.8.0"
},
"bin": {
"express": "./bin/express"
},
"scripts": {
"prepublish": "npm prune",
"test": "make test"
},
"engines": {
"node": ">= 0.8.0"
},
"license": "MIT"
"test": "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/ && cat ./coverage/lcov.info | coveralls"
}
}

View File

@@ -1,7 +1,7 @@
var express = require('../')
, Router = express.Router
, request = require('./support/http')
, request = require('supertest')
, methods = require('methods')
, assert = require('assert');

View File

@@ -1,13 +1,5 @@
var app = require('../../examples/auth/app')
, request = require('../support/http');
function redirects(to, fn){
return function(err, res){
res.statusCode.should.equal(302)
res.headers.should.have.property('location').match(to);
fn()
}
}
var request = require('supertest')
function getCookie(res) {
return res.headers['set-cookie'][0].split(';')[0];
@@ -18,25 +10,93 @@ describe('auth', function(){
it('should redirect to /login', function(done){
request(app)
.get('/')
.end(redirects(/\/login$/, done))
.expect('Location', '/login')
.expect(302, done)
})
})
describe('GET /restricted (w/o cookie)',function(){
it('should redirect to /login', function(done){
describe('GET /login',function(){
it('should render login form', function(done){
request(app)
.get('/restricted')
.end(redirects(/\/login$/,done))
.get('/login')
.expect(200, /<form/, done)
})
})
describe('POST /login', function(){
it('should fail without proper credentials', function(done){
it('should display login error', function(done){
request(app)
.post('/login')
.type('urlencoded')
.send('username=not-tj&password=foobar')
.end(redirects(/\/login$/, done))
.expect('Location', '/login')
.expect(302, function(err, res){
if (err) return done(err)
request(app)
.get('/login')
.set('Cookie', getCookie(res))
.expect(200, /Authentication failed/, done)
})
})
})
})
describe('GET /logout',function(){
it('should redirect to /', function(done){
request(app)
.get('/logout')
.expect('Location', '/')
.expect(302, done)
})
})
describe('GET /restricted',function(){
it('should redirect to /login without cookie', function(done){
request(app)
.get('/restricted')
.expect('Location', '/login')
.expect(302, done)
})
it('should succeed with proper cookie', function(done){
request(app)
.post('/login')
.type('urlencoded')
.send('username=tj&password=foobar')
.expect('Location', '/')
.expect(302, function(err, res){
if (err) return done(err)
request(app)
.get('/restricted')
.set('Cookie', getCookie(res))
.expect(200, done)
})
})
})
describe('POST /login', function(){
it('should fail without proper username', function(done){
request(app)
.post('/login')
.type('urlencoded')
.send('username=not-tj&password=foobar')
.expect('Location', '/login')
.expect(302, done)
})
it('should fail without proper password', function(done){
request(app)
.post('/login')
.type('urlencoded')
.send('username=tj&password=baz')
.expect('Location', '/login')
.expect(302, done)
})
it('should succeed with proper credentials', function(done){
request(app)
.post('/login')
.type('urlencoded')
.send('username=tj&password=foobar')
.expect('Location', '/')
.expect(302, done)
})
})
})

View File

@@ -1,5 +1,5 @@
var request = require('../support/http')
var request = require('supertest')
, app = require('../../examples/content-negotiation');
describe('content-negotiation', function(){

View File

@@ -1,6 +1,6 @@
var app = require('../../examples/cookies/app')
, request = require('../support/http');
, request = require('supertest');
describe('cookies', function(){
describe('GET /', function(){

View File

@@ -1,6 +1,6 @@
var app = require('../../examples/downloads/app')
, request = require('../support/http');
, request = require('supertest');
describe('downloads', function(){
describe('GET /', function(){

View File

@@ -1,5 +1,5 @@
var request = require('../support/http')
var request = require('supertest')
, app = require('../../examples/ejs');
describe('ejs', function(){

View File

@@ -1,6 +1,6 @@
var app = require('../../examples/error-pages')
, request = require('../support/http');
, request = require('supertest');
describe('error-pages', function(){
describe('GET /', function(){

View File

@@ -1,6 +1,6 @@
var app = require('../../examples/error')
, request = require('../support/http');
, request = require('supertest');
describe('error', function(){
describe('GET /', function(){

View File

@@ -1,6 +1,6 @@
var app = require('../../examples/markdown')
, request = require('../support/http');
, request = require('supertest');
describe('markdown', function(){
describe('GET /', function(){

View File

@@ -1,5 +1,5 @@
var request = require('../support/http')
var request = require('supertest')
, app = require('../../examples/mvc');
describe('mvc', function(){

View File

@@ -1,5 +1,5 @@
var app = require('../../examples/params/app')
, request = require('../support/http');
, request = require('supertest');
describe('params', function(){
describe('GET /', function(){

View File

@@ -1,5 +1,5 @@
var app = require('../../examples/resource/app')
, request = require('../support/http');
, request = require('supertest');
describe('resource', function(){
describe('GET /', function(){

View File

@@ -1,5 +1,5 @@
var request = require('../support/http')
var request = require('supertest')
, app = require('../../examples/web-service');
describe('web-service', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('app.all()', function(){
it('should add a router per method', function(done){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('app.del()', function(){
it('should alias app.delete()', function(done){

View File

@@ -1,7 +1,7 @@
var express = require('../')
, request = require('./support/http')
, assert = require('assert');
var express = require('../');
var request = require('supertest');
var assert = require('assert');
describe('HEAD', function(){
it('should default to GET', function(done){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('app.listen()', function(){
it('should wrap with an HTTP server', function(done){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('app', function(){
describe('.locals(obj)', function(){
@@ -14,7 +14,7 @@ describe('app', function(){
app.locals.age.should.equal(2);
})
})
describe('.locals.settings', function(){
it('should expose app settings', function(){
var app = express();

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('OPTIONS', function(){
it('should default to the routes defined', function(done){
@@ -58,4 +58,4 @@ describe('app.options()', function(){
.expect('GET')
.expect('Allow', 'GET', done);
})
})
})

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('app', function(){
describe('.param(fn)', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('app', function(){
describe('.request', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('app', function(){
describe('.response', function(){
@@ -19,7 +19,7 @@ describe('app', function(){
.get('/')
.expect('HEY', done);
})
it('should not be influenced by other app protos', function(done){
var app = express()
, app2 = express();
@@ -27,7 +27,7 @@ describe('app', function(){
app.response.shout = function(str){
this.send(str.toUpperCase());
};
app2.response.shout = function(str){
this.send(str);
};

View File

@@ -1,5 +1,5 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('app', function(){
describe('.VERB()', function(){

View File

@@ -1,7 +1,7 @@
var express = require('../')
, assert = require('assert')
, request = require('./support/http');
, request = require('supertest');
describe('app.routes', function(){
it('should be initialized', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('app', function(){
it('should emit "mount" when mounted', function(done){
@@ -23,7 +23,7 @@ describe('app', function(){
blog.get('/blog', function(req, res){
res.end('blog');
});
app.use(blog);
request(app)

View File

@@ -1,7 +1,7 @@
var express = require('../')
, request = require('./support/http')
, assert = require('assert');
var express = require('../');
var request = require('supertest');
var assert = require('assert');
describe('exports', function(){
it('should expose connect middleware', function(){

View File

@@ -1,6 +1,6 @@
//
// var express = require('../')
// , request = require('./support/http');
// , request = require('supertest');
//
// describe('middleware', function(){
// describe('.next()', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('throw after .end()', function(){
it('should fail gracefully', function(done){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.accepted', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.acceptedCharsets', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.acceptedEncodings', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.acceptedLanguages', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.accepts(type)', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.acceptsCharset(type)', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.auth', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.fresh', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http')
, request = require('supertest')
, assert = require('assert');
describe('req', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http')
, request = require('supertest')
, assert = require('assert');
describe('req', function(){
@@ -69,5 +69,70 @@ describe('req', function(){
.set('Host', '[::1]:3000')
.expect('[::1]', done);
})
describe('when "trust proxy" is enabled', function(){
it('should respect X-Forwarded-Host', function(done){
var app = express();
app.enable('trust proxy');
app.use(function(req, res){
res.end(req.host);
});
request(app)
.get('/')
.set('Host', 'localhost')
.set('X-Forwarded-Host', 'example.com')
.expect('example.com', done);
})
it('should ignore X-Forwarded-Host if socket addr not trusted', function(done){
var app = express();
app.set('trust proxy', '10.0.0.1');
app.use(function(req, res){
res.end(req.host);
});
request(app)
.get('/')
.set('Host', 'localhost')
.set('X-Forwarded-Host', 'example.com')
.expect('localhost', done);
})
it('should default to Host', function(done){
var app = express();
app.enable('trust proxy');
app.use(function(req, res){
res.end(req.host);
});
request(app)
.get('/')
.set('Host', 'example.com')
.expect('example.com', done);
})
})
describe('when "trust proxy" is disabled', function(){
it('should ignore X-Forwarded-Host', function(done){
var app = express();
app.use(function(req, res){
res.end(req.host);
});
request(app)
.get('/')
.set('Host', 'localhost')
.set('X-Forwarded-Host', 'evil')
.expect('localhost', done);
})
})
})
})

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.ip', function(){
@@ -20,6 +20,21 @@ describe('req', function(){
.set('X-Forwarded-For', 'client, p1, p2')
.expect('client', done);
})
it('should return the addr after trusted proxy', function(done){
var app = express();
app.set('trust proxy', 2);
app.use(function(req, res, next){
res.send(req.ip);
});
request(app)
.get('/')
.set('X-Forwarded-For', 'client, p1, p2')
.expect('p1', done);
})
})
describe('when "trust proxy" is disabled', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.ips', function(){
@@ -20,6 +20,21 @@ describe('req', function(){
.set('X-Forwarded-For', 'client, p1, p2')
.expect('["client","p1","p2"]', done);
})
it('should stop at first untrusted', function(done){
var app = express();
app.set('trust proxy', 2);
app.use(function(req, res, next){
res.send(req.ips);
});
request(app)
.get('/')
.set('X-Forwarded-For', 'client, p1, p2')
.expect('["p1","p2"]', done);
})
})
describe('when "trust proxy" is disabled', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
function req(ct) {
var req = {

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest')
describe('req', function(){
describe('.param(name, default)', function(){
@@ -29,7 +29,7 @@ describe('req', function(){
.get('/?name=tj')
.expect('tj', done);
})
it('should check req.body', function(done){
var app = express();
@@ -44,7 +44,7 @@ describe('req', function(){
.send({ name: 'tj' })
.expect('tj', done);
})
it('should check req.params', function(done){
var app = express();

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.path', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.protocol', function(){
@@ -32,6 +32,21 @@ describe('req', function(){
.expect('https', done);
})
it('should ignore X-Forwarded-Proto if socket addr not trusted', function(done){
var app = express();
app.set('trust proxy', '10.0.0.1');
app.use(function(req, res){
res.end(req.protocol);
});
request(app)
.get('/')
.set('X-Forwarded-Proto', 'https')
.expect('http', done);
})
it('should default to http', function(done){
var app = express();

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.query', function(){
@@ -18,7 +18,7 @@ describe('req', function(){
done();
});
})
it('should contain the parsed query-string', function(done){
var app = express();

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.route', function(){
@@ -12,7 +12,7 @@ describe('req', function(){
req.route.path.should.equal('/user/:id/:op?');
next();
});
app.get('/user/:id/edit', function(req, res){
req.route.method.should.equal('get');
req.route.path.should.equal('/user/:id/edit');

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.secure', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest')
describe('req', function(){
describe('.signedCookies', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.stale', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.subdomains', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('req', function(){
describe('.xhr', function(){
@@ -19,7 +19,7 @@ describe('req', function(){
done();
})
})
it('should case-insensitive', function(done){
var app = express();
@@ -35,7 +35,7 @@ describe('req', function(){
done();
})
})
it('should return false otherwise', function(done){
var app = express();
@@ -51,7 +51,7 @@ describe('req', function(){
done();
})
})
it('should return false when not present', function(done){
var app = express();

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('res', function(){
describe('.attachment()', function(){
@@ -16,7 +16,7 @@ describe('res', function(){
.expect('Content-Disposition', 'attachment', done);
})
})
describe('.attachment(filename)', function(){
it('should add the filename param', function(done){
var app = express();
@@ -30,7 +30,7 @@ describe('res', function(){
.get('/')
.expect('Content-Disposition', 'attachment; filename="image.png"', done);
})
it('should set the Content-Type', function(done){
var app = express();

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('res', function(){
describe('.charset', function(){
@@ -17,7 +17,7 @@ describe('res', function(){
.get('/')
.expect("text/x-foo; charset=utf-8", done);
})
it('should take precedence over res.send() defaults', function(done){
var app = express();

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('res', function(){
describe('.clearCookie(name)', function(){
@@ -20,7 +20,7 @@ describe('res', function(){
})
})
})
describe('.clearCookie(name, options)', function(){
it('should set the given params', function(done){
var app = express();

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http')
, request = require('supertest')
, utils = require('connect').utils
, cookie = require('cookie');
@@ -39,7 +39,7 @@ describe('res', function(){
done();
})
})
it('should allow multiple calls', function(done){
var app = express();
@@ -58,7 +58,7 @@ describe('res', function(){
})
})
})
describe('.cookie(name, string, options)', function(){
it('should set params', function(done){
var app = express();
@@ -76,7 +76,7 @@ describe('res', function(){
done();
})
})
describe('maxAge', function(){
it('should set relative expires', function(done){
var app = express();

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http')
, request = require('supertest')
, assert = require('assert');
describe('res', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http')
, request = require('supertest')
, utils = require('../lib/utils')
, assert = require('assert');
@@ -15,7 +15,7 @@ app1.use(function(req, res, next){
'text/html': function(){
res.send('<p>hey</p>');
},
'application/json': function(a, b, c){
assert(req == a);
assert(res == b);

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http')
, request = require('supertest')
, assert = require('assert');
describe('res', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http')
, request = require('supertest')
, assert = require('assert');
describe('res', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('res', function(){
describe('.locals(obj)', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('res', function(){
describe('.location(url)', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('res', function(){
describe('.redirect(url)', function(){

View File

@@ -1,12 +1,12 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('res', function(){
describe('.render(name)', function(){
it('should support absolute paths', function(done){
var app = express();
app.locals.user = { name: 'tobi' };
app.use(function(req, res){
@@ -17,10 +17,10 @@ describe('res', function(){
.get('/')
.expect('<p>tobi</p>', done);
})
it('should support absolute paths with "view engine"', function(done){
var app = express();
app.locals.user = { name: 'tobi' };
app.set('view engine', 'jade');
@@ -35,7 +35,7 @@ describe('res', function(){
it('should expose app.locals', function(done){
var app = express();
app.set('views', __dirname + '/fixtures');
app.locals.user = { name: 'tobi' };
@@ -50,29 +50,29 @@ describe('res', function(){
it('should support index.<engine>', function(done){
var app = express();
app.set('views', __dirname + '/fixtures');
app.set('view engine', 'jade');
app.use(function(req, res){
res.render('blog/post');
});
request(app)
.get('/')
.expect('<h1>blog post</h1>', done);
})
describe('when an error occurs', function(){
it('should next(err)', function(done){
var app = express();
app.set('views', __dirname + '/fixtures');
app.use(function(req, res){
res.render('user.jade');
});
app.use(function(err, req, res, next){
res.end(err.message);
});
@@ -82,11 +82,11 @@ describe('res', function(){
.expect(/user is not defined/, done);
})
})
describe('when "view engine" is given', function(){
it('should render the template', function(done){
var app = express();
app.set('view engine', 'jade');
app.set('views', __dirname + '/fixtures');
@@ -104,9 +104,9 @@ describe('res', function(){
describe('.render(name, option)', function(){
it('should render the template', function(done){
var app = express();
app.set('views', __dirname + '/fixtures');
var user = { name: 'tobi' };
app.use(function(req, res){
@@ -117,10 +117,10 @@ describe('res', function(){
.get('/')
.expect('<p>tobi</p>', done);
})
it('should expose app.locals', function(done){
var app = express();
app.set('views', __dirname + '/fixtures');
app.locals.user = { name: 'tobi' };
@@ -132,10 +132,10 @@ describe('res', function(){
.get('/')
.expect('<p>tobi</p>', done);
})
it('should expose res.locals', function(done){
var app = express();
app.set('views', __dirname + '/fixtures');
app.use(function(req, res){
@@ -147,10 +147,10 @@ describe('res', function(){
.get('/')
.expect('<p>tobi</p>', done);
})
it('should give precedence to res.locals over app.locals', function(done){
var app = express();
app.set('views', __dirname + '/fixtures');
app.locals.user = { name: 'tobi' };
@@ -166,10 +166,10 @@ describe('res', function(){
it('should give precedence to res.render() locals over res.locals', function(done){
var app = express();
app.set('views', __dirname + '/fixtures');
var jane = { name: 'jane' };
app.use(function(req, res){
res.locals.user = { name: 'tobi' };
res.render('user.jade', { user: jane });
@@ -179,14 +179,14 @@ describe('res', function(){
.get('/')
.expect('<p>jane</p>', done);
})
it('should give precedence to res.render() locals over app.locals', function(done){
var app = express();
app.set('views', __dirname + '/fixtures');
app.locals.user = { name: 'tobi' };
var jane = { name: 'jane' };
app.use(function(req, res){
res.render('user.jade', { user: jane });
});

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http')
, request = require('supertest')
, assert = require('assert');
describe('res', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http')
, request = require('supertest')
, assert = require('assert');
describe('res', function(){
@@ -42,7 +42,7 @@ describe('res', function(){
app.use(function(req, res){
res.sendfile('test/fixtures/nope.html', function(err){
++calls;
assert(!res.headerSent);
assert(!res.headersSent);
res.send(err.message);
});
});
@@ -77,7 +77,7 @@ describe('res', function(){
app.use(function(req, res){
res.sendfile('test/fixtures/foo/../user.html', function(err){
assert(!res.headerSent);
assert(!res.headersSent);
++calls;
res.send(err.message);
});
@@ -95,7 +95,7 @@ describe('res', function(){
app.use(function(req, res){
res.sendfile('test/fixtures/user.html', function(err){
assert(!res.headerSent);
assert(!res.headersSent);
req.socket.listeners('error').should.have.length(1); // node's original handler
done();
});

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http')
, request = require('supertest')
, res = express.response;
describe('res', function(){
@@ -45,7 +45,7 @@ describe('res', function(){
JSON.stringify(res.get('ETag')).should.equal('["123","456"]');
})
})
describe('.set(object)', function(){
it('should set multiple fields', function(done){
var app = express();

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('res', function(){
describe('.status(code)', function(){

View File

@@ -1,6 +1,6 @@
var express = require('../')
, request = require('./support/http');
, request = require('supertest');
describe('res', function(){
describe('.type(str)', function(){

2
test/support/env.js Normal file
View File

@@ -0,0 +1,2 @@
process.env.NODE_ENV = 'test';

View File

@@ -1,2 +0,0 @@
module.exports = require('supertest');