Skip to content

Commit b40e74d

Browse files
committed
Fix "trust proxy" setting to inherit when app is mounted
fixes expressjs#2550 fixes expressjs#2551
1 parent eaf3318 commit b40e74d

File tree

5 files changed

+133
-33
lines changed

5 files changed

+133
-33
lines changed

History.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
3.x
22
===
33

4+
* Fix `"trust proxy"` setting to inherit when app is mounted
45
* Generate `ETag`s for all request responses
56
- No longer restricted to only responses for `GET` and `HEAD` requests
67
* Use `content-type` to parse `Content-Type` headers

lib/application.js

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1+
/*!
2+
* express
3+
* Copyright(c) 2009-2013 TJ Holowaychuk
4+
* Copyright(c) 2013 Roman Shtylman
5+
* Copyright(c) 2014-2015 Douglas Christopher Wilson
6+
* MIT Licensed
7+
*/
8+
19
/**
210
* Module dependencies.
11+
* @api private
312
*/
413

514
var connect = require('connect')
@@ -21,6 +30,13 @@ var merge = require('utils-merge');
2130

2231
var app = exports = module.exports = {};
2332

33+
/**
34+
* Variable for trust proxy inheritance back-compat
35+
* @api private
36+
*/
37+
38+
var trustProxyDefaultSymbol = '@@symbol:trust_proxy_default';
39+
2440
/**
2541
* Initialize the server.
2642
*
@@ -53,14 +69,27 @@ app.defaultConfiguration = function(){
5369
this.set('subdomain offset', 2);
5470
this.set('trust proxy', false);
5571

72+
// trust proxy inherit back-compat
73+
Object.defineProperty(this.settings, trustProxyDefaultSymbol, {
74+
configurable: true,
75+
value: true
76+
});
77+
5678
debug('booting in %s mode', env);
5779

5880
// implicit middleware
5981
this.use(connect.query());
6082
this.use(middleware.init(this));
6183

62-
// inherit protos
63-
this.on('mount', function(parent){
84+
this.on('mount', function onmount(parent) {
85+
// inherit trust proxy
86+
if (this.settings[trustProxyDefaultSymbol] === true
87+
&& typeof parent.settings['trust proxy fn'] === 'function') {
88+
delete this.settings['trust proxy'];
89+
delete this.settings['trust proxy fn'];
90+
}
91+
92+
// inherit protos
6493
this.request.__proto__ = parent.request;
6594
this.response.__proto__ = parent.response;
6695
this.engines.__proto__ = parent.engines;
@@ -271,6 +300,13 @@ app.set = function(setting, val){
271300
case 'trust proxy':
272301
debug('compile trust proxy %s', val);
273302
this.set('trust proxy fn', compileTrust(val));
303+
304+
// trust proxy inherit back-compat
305+
Object.defineProperty(this.settings, trustProxyDefaultSymbol, {
306+
configurable: true,
307+
value: false
308+
});
309+
274310
break;
275311
}
276312

test/app.use.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

2-
var express = require('../')
3-
, request = require('supertest');
2+
var assert = require('assert');
3+
var express = require('..');
4+
var request = require('supertest');
45

56
describe('app', function(){
67
it('should emit "mount" when mounted', function(done){

test/config.js

Lines changed: 74 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,36 @@
11

2-
var express = require('../')
3-
, assert = require('assert');
2+
var assert = require('assert');
3+
var express = require('..');
44

5-
describe('config', function(){
6-
describe('.set()', function(){
7-
it('should set a value', function(){
5+
describe('config', function () {
6+
describe('.set()', function () {
7+
it('should set a value', function () {
88
var app = express();
9-
app.set('foo', 'bar').should.equal(app);
9+
app.set('foo', 'bar');
10+
assert.equal(app.get('foo'), 'bar');
11+
})
12+
13+
it('should return the app', function () {
14+
var app = express();
15+
assert.equal(app.set('foo', 'bar'), app);
1016
})
1117

12-
it('should return the app when undefined', function(){
18+
it('should return the app when undefined', function () {
1319
var app = express();
14-
app.set('foo', undefined).should.equal(app);
20+
assert.equal(app.set('foo', undefined), app);
1521
})
1622

1723
describe('"etag"', function(){
1824
it('should throw on bad value', function(){
19-
var app = express()
20-
app.set.bind(app, 'etag', 42).should.throw(/unknown value/)
25+
var app = express();
26+
assert.throws(app.set.bind(app, 'etag', 42), /unknown value/);
2127
})
2228

2329
it('should set "etag fn"', function(){
2430
var app = express()
2531
var fn = function(){}
2632
app.set('etag', fn)
27-
app.get('etag fn').should.equal(fn)
33+
assert.equal(app.get('etag fn'), fn)
2834
})
2935
})
3036

@@ -33,85 +39,124 @@ describe('config', function(){
3339
var app = express()
3440
var fn = function(){}
3541
app.set('trust proxy', fn)
36-
app.get('trust proxy fn').should.equal(fn)
42+
assert.equal(app.get('trust proxy fn'), fn)
3743
})
3844
})
3945
})
4046

4147
describe('.get()', function(){
4248
it('should return undefined when unset', function(){
4349
var app = express();
44-
assert(undefined === app.get('foo'));
50+
assert.strictEqual(app.get('foo'), undefined);
4551
})
4652

4753
it('should otherwise return the value', function(){
4854
var app = express();
4955
app.set('foo', 'bar');
50-
app.get('foo').should.equal('bar');
56+
assert.equal(app.get('foo'), 'bar');
5157
})
5258

5359
describe('when mounted', function(){
5460
it('should default to the parent app', function(){
55-
var app = express()
56-
, blog = express();
61+
var app = express();
62+
var blog = express();
5763

5864
app.set('title', 'Express');
5965
app.use(blog);
60-
blog.get('title').should.equal('Express');
66+
assert.equal(blog.get('title'), 'Express');
6167
})
62-
68+
6369
it('should given precedence to the child', function(){
64-
var app = express()
65-
, blog = express();
70+
var app = express();
71+
var blog = express();
6672

6773
app.use(blog);
6874
app.set('title', 'Express');
6975
blog.set('title', 'Some Blog');
7076

71-
blog.get('title').should.equal('Some Blog');
77+
assert.equal(blog.get('title'), 'Some Blog');
78+
})
79+
80+
it('should inherit "trust proxy" setting', function () {
81+
var app = express();
82+
var blog = express();
83+
84+
function fn() { return false }
85+
86+
app.set('trust proxy', fn);
87+
assert.equal(app.get('trust proxy'), fn);
88+
assert.equal(app.get('trust proxy fn'), fn);
89+
90+
app.use(blog);
91+
92+
assert.equal(blog.get('trust proxy'), fn);
93+
assert.equal(blog.get('trust proxy fn'), fn);
94+
})
95+
96+
it('should prefer child "trust proxy" setting', function () {
97+
var app = express();
98+
var blog = express();
99+
100+
function fn1() { return false }
101+
function fn2() { return true }
102+
103+
app.set('trust proxy', fn1);
104+
assert.equal(app.get('trust proxy'), fn1);
105+
assert.equal(app.get('trust proxy fn'), fn1);
106+
107+
blog.set('trust proxy', fn2);
108+
assert.equal(blog.get('trust proxy'), fn2);
109+
assert.equal(blog.get('trust proxy fn'), fn2);
110+
111+
app.use(blog);
112+
113+
assert.equal(app.get('trust proxy'), fn1);
114+
assert.equal(app.get('trust proxy fn'), fn1);
115+
assert.equal(blog.get('trust proxy'), fn2);
116+
assert.equal(blog.get('trust proxy fn'), fn2);
72117
})
73118
})
74119
})
75120

76121
describe('.enable()', function(){
77122
it('should set the value to true', function(){
78123
var app = express();
79-
app.enable('tobi').should.equal(app);
80-
app.get('tobi').should.be.true;
124+
assert.equal(app.enable('tobi'), app);
125+
assert.strictEqual(app.get('tobi'), true);
81126
})
82127
})
83128

84129
describe('.disable()', function(){
85130
it('should set the value to false', function(){
86131
var app = express();
87-
app.disable('tobi').should.equal(app);
88-
app.get('tobi').should.be.false;
132+
assert.equal(app.disable('tobi'), app);
133+
assert.strictEqual(app.get('tobi'), false);
89134
})
90135
})
91136

92137
describe('.enabled()', function(){
93138
it('should default to false', function(){
94139
var app = express();
95-
app.enabled('foo').should.be.false;
140+
assert.strictEqual(app.enabled('foo'), false);
96141
})
97142

98143
it('should return true when set', function(){
99144
var app = express();
100145
app.set('foo', 'bar');
101-
app.enabled('foo').should.be.true;
146+
assert.strictEqual(app.enabled('foo'), true);
102147
})
103148
})
104149

105150
describe('.disabled()', function(){
106151
it('should default to true', function(){
107152
var app = express();
108-
app.disabled('foo').should.be.true;
153+
assert.strictEqual(app.disabled('foo'), true);
109154
})
110155

111156
it('should return false when set', function(){
112157
var app = express();
113158
app.set('foo', 'bar');
114-
app.disabled('foo').should.be.false;
159+
assert.strictEqual(app.disabled('foo'), false);
115160
})
116161
})
117162
})

test/req.ip.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,23 @@ describe('req', function(){
3535
.set('X-Forwarded-For', 'client, p1, p2')
3636
.expect('p1', done);
3737
})
38+
39+
it('should return the addr after trusted proxy, from sub app', function (done) {
40+
var app = express();
41+
var sub = express();
42+
43+
app.set('trust proxy', 2);
44+
app.use(sub);
45+
46+
sub.use(function (req, res, next) {
47+
res.send(req.ip);
48+
});
49+
50+
request(app)
51+
.get('/')
52+
.set('X-Forwarded-For', 'client, p1, p2')
53+
.expect(200, 'p1', done);
54+
})
3855
})
3956

4057
describe('when "trust proxy" is disabled', function(){

0 commit comments

Comments
 (0)