diff --git a/lib/request.js b/lib/request.js index 7881d4c60..443b66b44 100644 --- a/lib/request.js +++ b/lib/request.js @@ -5,7 +5,7 @@ * Module dependencies. */ -const URL = require('url').URL; +const url = require('url'); const net = require('net'); const contentType = require('content-type'); const stringify = require('url').format; @@ -283,7 +283,7 @@ module.exports = { const host = this.host; const originalUrl = this.originalUrl || ''; // avoid undefined in template string try { - this.memoizedURL = new URL(`${protocol}://${host}${originalUrl}`); + this.memoizedURL = new url.URL(`${protocol}://${host}${originalUrl}`); } catch (err) { this.memoizedURL = Object.create(null); } @@ -433,6 +433,15 @@ module.exports = { const val = this.get('X-Forwarded-For'); return proxy && val ? val.split(/\s*,\s*/) + .map(host => { + let normalizedHost = host; + if (net.isIPv6(host)) { + normalizedHost = `[${host}]`; + } + + return url.parse(`http://${normalizedHost}`).hostname; + }) + .filter(ip => !!ip) : []; }, diff --git a/test/request/ips.js b/test/request/ips.js index 8e0a5f0c7..65478f09d 100644 --- a/test/request/ips.js +++ b/test/request/ips.js @@ -23,5 +23,23 @@ describe('req.ips', () => { assert.deepEqual(req.ips, ['127.0.0.1', '127.0.0.2']); }); }); + + describe('and contains IPv4', () => { + it('should not return port', () => { + const req = request(); + req.app.proxy = true; + req.header['x-forwarded-for'] = '127.0.0.1:80,127.0.0.2'; + assert.deepEqual(req.ips, ['127.0.0.1', '127.0.0.2']); + }); + }); + + describe('and contains IPv6', () => { + it('should parse correctly', () => { + const req = request(); + req.app.proxy = true; + req.header['x-forwarded-for'] = '::1'; + assert.deepEqual(req.ips, ['::1']); + }); + }); }); });