diff --git a/lib/request.js b/lib/request.js index c0506334ce2..c0ee7a2b5b9 100644 --- a/lib/request.js +++ b/lib/request.js @@ -386,9 +386,14 @@ defineGetter(req, 'subdomains', function subdomains() { if (!hostname) return []; var offset = this.app.get('subdomain offset'); - var subdomains = !isIP(hostname) - ? hostname.split('.').reverse() - : [hostname]; + // An IPv6 literal keeps its brackets (e.g. "[::ffff:127.0.0.1]"), which + // net.isIP() rejects, so detect it by the brackets and keep it as a single + // unit instead of splitting it on its dots. + var subdomains = hostname[0] === '[' && hostname[hostname.length - 1] === ']' + ? [hostname] + : !isIP(hostname) + ? hostname.split('.').reverse() + : [hostname]; return subdomains.slice(offset); }); diff --git a/test/req.subdomains.js b/test/req.subdomains.js index e5600f2eb56..e80e9d1df2b 100644 --- a/test/req.subdomains.js +++ b/test/req.subdomains.js @@ -44,6 +44,19 @@ describe('req', function(){ .set('Host', '[::1]') .expect(200, [], done); }) + + it('should work with a dotted IPv6 address', function(done){ + var app = express(); + + app.use(function(req, res){ + res.send(req.subdomains); + }); + + request(app) + .get('/') + .set('Host', '[::ffff:127.0.0.1]') + .expect(200, [], done); + }) }) describe('otherwise', function(){ @@ -135,6 +148,20 @@ describe('req', function(){ .set('Host', '[::1]') .expect(200, ['[::1]'], done); }) + + it('should return an array with the whole dotted IPv6', function (done) { + var app = express(); + app.set('subdomain offset', 0); + + app.use(function(req, res){ + res.send(req.subdomains); + }); + + request(app) + .get('/') + .set('Host', '[::ffff:127.0.0.1]') + .expect(200, ['[::ffff:127.0.0.1]'], done); + }) }) describe('when present', function(){