diff --git a/lib/request.js b/lib/request.js index ddcace86e..4597680bf 100644 --- a/lib/request.js +++ b/lib/request.js @@ -433,12 +433,28 @@ module.exports = { get ips() { const proxy = this.app.proxy; const val = this.get(this.app.proxyIpHeader); - let ips = proxy && val - ? val.split(/\s*,\s*/) - : []; + let ips = []; + + if (proxy && val) { + ips = val.split(/\s*,\s*/) + .map(host => { + let normalizedHost = host; + + if (net.isIPv6(host)) { + normalizedHost = `[${host}]`; + } + + const hostname = new URL(`http://${normalizedHost}`).hostname; + + return hostname.replace(/(^\[|\]$)/g, ''); + }) + .filter(ip => !!ip); + } + if (this.app.maxIpsCount > 0) { ips = ips.slice(-this.app.maxIpsCount); } + return ips; }, diff --git a/test/request/ips.js b/test/request/ips.js index 18ec82ea4..86c77fc61 100644 --- a/test/request/ips.js +++ b/test/request/ips.js @@ -23,6 +23,24 @@ 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']); + }); + }); }); describe('when options.proxyIpHeader is present', () => {