New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle missing Host: header #1579
Changes from 7 commits
823093c
1731031
bdd61a2
2798c5b
4f08f52
de85476
cfbd895
d283256
7fa0290
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
|
||
/** | ||
* Module dependencies. | ||
*/ | ||
|
@@ -445,7 +444,9 @@ req.__defineGetter__('auth', function(){ | |
|
||
req.__defineGetter__('subdomains', function(){ | ||
var offset = this.app.get('subdomain offset'); | ||
return this.get('Host') | ||
var host = this.get('Host'); | ||
if (!host) return []; | ||
return host | ||
.split('.') | ||
.reverse() | ||
.slice(offset); | ||
|
@@ -472,7 +473,10 @@ req.__defineGetter__('path', function(){ | |
req.__defineGetter__('host', function(){ | ||
var trustProxy = this.app.get('trust proxy'); | ||
var host = trustProxy && this.get('X-Forwarded-Host'); | ||
host = host || this.get('Host'); | ||
if (host === false || typeof host === 'undefined') // If X-Forwarded-Host is present but empty, return it. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh oops read that wrong, this seems a little weird to me still though There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Javascript truthiness strikes again! This allows missing headers, or |
||
host = this.get('Host'); | ||
if (typeof host === 'undefined') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this one wont need the typeof just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No;
It certainly is less clean that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No;
It certainly is less clean that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not true, typeof isn't necessary unless something may not be declared, which is very rare. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True, but I prefer to be more explicit (using strict equality). |
||
return null; | ||
return host.split(':')[0]; | ||
}); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
|
||
var express = require('../') | ||
, request = require('./support/http'); | ||
|
||
|
||
describe('req', function(){ | ||
describe('.host', function(){ | ||
describe('when X-Forwarded-Host is present', function(){ | ||
describe('when "trust proxy" is enabled', function(){ | ||
it('should return the forwarded header', function (done) { | ||
var app = express(); | ||
|
||
app.enable('trust proxy'); | ||
|
||
app.use(function (req, res, next) { | ||
res.send(req.host); | ||
}); | ||
|
||
request(app) | ||
.get('/') | ||
.set('Host', 'proxy.example.com:80') | ||
.set('X-Forwarded-Host', 'example.com:80') | ||
.expect('example.com', done); | ||
}) | ||
it('should return the forwarded header even if empty', function (done) { | ||
var app = express(); | ||
|
||
app.enable('trust proxy'); | ||
|
||
app.use(function (req, res, next) { | ||
res.send(req.host); | ||
}); | ||
|
||
request(app) | ||
.get('/') | ||
.set('Host', 'proxy.example.com:80') | ||
.set('X-Forwarded-Host', '') | ||
.expect('', done); | ||
}) | ||
it('should return null when there are no headers', function (done) { | ||
var app = express(); | ||
|
||
app.enable('trust proxy'); | ||
|
||
app.use(function (req, res, next) { | ||
res.send(JSON.stringify(req.host)); | ||
}); | ||
|
||
request(app) | ||
.get('/') | ||
.unset('Host') | ||
.expect('null', done); | ||
}) | ||
}) | ||
|
||
describe('when "trust proxy" is disabled', function(){ | ||
it('should return null when there is no Host header', function (done) { | ||
var app = express(); | ||
|
||
app.use(function (req, res, next) { | ||
res.send(JSON.stringify(req.host)); | ||
}); | ||
|
||
request(app) | ||
.get('/') | ||
.set('X-Forwarded-Host', 'example.com:80') | ||
.unset('Host') | ||
.expect('null', done); | ||
}) | ||
it('should return empty string when there is an empty Host header', function (done) { | ||
var app = express(); | ||
|
||
app.use(function (req, res, next) { | ||
res.send(req.host); | ||
}); | ||
|
||
request(app) | ||
.get('/') | ||
.set('X-Forwarded-Host', 'example.com:80') | ||
.set('Host', '') | ||
.expect('', done); | ||
}) | ||
it('should return the actual host address', function(done){ | ||
var app = express(); | ||
|
||
app.use(function(req, res, next){ | ||
res.send(req.host); | ||
}); | ||
|
||
request(app) | ||
.get('/') | ||
.set('Host', 'proxy.example.com:80') | ||
.set('X-Forwarded-Host', 'example.com:80') | ||
.expect('proxy.example.com', done); | ||
}) | ||
}) | ||
}) | ||
|
||
describe('when X-Forwarded-Host is not present', function () { | ||
it('should return the domain only', function(done){ | ||
var app = express(); | ||
|
||
app.use(function(req, res, next){ | ||
res.send(req.host); | ||
}); | ||
|
||
request(app) | ||
.get('/') | ||
.set('Host', 'example.com:8080') | ||
.expect('example.com', done); | ||
}) | ||
it('should return the domain only even when there is no port', function(done){ | ||
var app = express(); | ||
|
||
app.use(function(req, res, next){ | ||
res.send(req.host); | ||
}); | ||
|
||
request(app) | ||
.get('/') | ||
.set('Host', 'example.com') | ||
.expect('example.com', done); | ||
}) | ||
it('should return null when there is no Host header', function (done) { | ||
var app = express(); | ||
|
||
app.use(function(req, res, next){ | ||
res.send(JSON.stringify(req.host)); | ||
}); | ||
|
||
request(app) | ||
.get('/') | ||
.unset('Host') | ||
.expect('null', done); | ||
}) | ||
it('should return empty string when there is an empty Host header', function (done) { | ||
var app = express(); | ||
|
||
app.use(function (req, res, next) { | ||
res.send(req.host); | ||
}); | ||
|
||
request(app) | ||
.get('/') | ||
.set('Host', '') | ||
.expect('', done); | ||
}) | ||
}) | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,11 +19,11 @@ describe('req', function(){ | |
}) | ||
}) | ||
|
||
describe('otherwise', function(){ | ||
it('should return an empty array', function(done){ | ||
describe('otherwise', function () { | ||
it('should return an empty array', function (done) { | ||
var app = express(); | ||
|
||
app.use(function(req, res){ | ||
app.use(function (req, res) { | ||
res.send(req.subdomains); | ||
}); | ||
|
||
|
@@ -34,6 +34,35 @@ describe('req', function(){ | |
}) | ||
}) | ||
|
||
describe('when there is no Host header', function () { | ||
it('should return an empty array', function (done) { | ||
var app = express(); | ||
|
||
app.use(function (req, res, next) { | ||
res.send(req.subdomains); | ||
}); | ||
|
||
request(app) | ||
.get('/') | ||
.unset('Host') | ||
.expect([], done); | ||
}) | ||
}) | ||
describe('when there is an empty Host header', function () { | ||
it('should return an empty array', function (done) { | ||
var app = express(); | ||
|
||
app.use(function (req, res, next) { | ||
res.send(req.subdomains); | ||
}); | ||
|
||
request(app) | ||
.get('/') | ||
.set('Host', '') | ||
.expect([], done); | ||
}) | ||
}) | ||
|
||
describe('when subdomain offset is set', function(){ | ||
describe('when subdomain offset is zero', function(){ | ||
it('should return an array with the whole domain', function(done){ | ||
|
@@ -49,6 +78,37 @@ describe('req', function(){ | |
.set('Host', 'tobi.ferrets.sub.example.com') | ||
.expect('["com","example","sub","ferrets","tobi"]', done); | ||
}) | ||
|
||
describe('when there is no Host header', function () { | ||
it('should return an empty array', function (done) { | ||
var app = express(); | ||
app.set('subdomain offset', 0); | ||
|
||
app.use(function (req, res, next) { | ||
res.send(req.subdomains); | ||
}); | ||
|
||
request(app) | ||
.get('/') | ||
.unset('Host') | ||
.expect([], done); | ||
}) | ||
}) | ||
describe('when there is an empty Host header', function () { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rad thanks for all the tests, only nitpick is a newline after each of these so they're not squished together, and There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
it('should return an empty array', function (done) { | ||
var app = express(); | ||
app.set('subdomain offset', 0); | ||
|
||
app.use(function (req, res, next) { | ||
res.send(req.subdomains); | ||
}); | ||
|
||
request(app) | ||
.get('/') | ||
.set('Host', '') | ||
.expect([], done); | ||
}) | ||
}) | ||
}) | ||
|
||
describe('when present', function(){ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,6 @@ | ||
|
||
module.exports = require('supertest'); | ||
module.exports = require('supertest'); | ||
module.exports.Test.prototype.unset = function (field) { | ||
this.request().removeHeader(field); | ||
return this; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could use
this.host
here since we already handle itThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes; in fact,
subdomains
currently ignorestrust proxy
completely, which is a bug.