| /*! |
| * forwarded |
| * Copyright(c) 2014-2017 Douglas Christopher Wilson |
| * MIT Licensed |
| */ |
| |
| 'use strict' |
| |
| /** |
| * Module exports. |
| * @public |
| */ |
| |
| module.exports = forwarded |
| |
| /** |
| * Get all addresses in the request, using the `X-Forwarded-For` header. |
| * |
| * @param {object} req |
| * @return {array} |
| * @public |
| */ |
| |
| function forwarded (req) { |
| if (!req) { |
| throw new TypeError('argument req is required') |
| } |
| |
| // simple header parsing |
| var proxyAddrs = parse(req.headers['x-forwarded-for'] || '') |
| var socketAddr = req.connection.remoteAddress |
| var addrs = [socketAddr].concat(proxyAddrs) |
| |
| // return all addresses |
| return addrs |
| } |
| |
| /** |
| * Parse the X-Forwarded-For header. |
| * |
| * @param {string} header |
| * @private |
| */ |
| |
| function parse (header) { |
| var end = header.length |
| var list = [] |
| var start = header.length |
| |
| // gather addresses, backwards |
| for (var i = header.length - 1; i >= 0; i--) { |
| switch (header.charCodeAt(i)) { |
| case 0x20: /* */ |
| if (start === end) { |
| start = end = i |
| } |
| break |
| case 0x2c: /* , */ |
| if (start !== end) { |
| list.push(header.substring(start, end)) |
| } |
| start = end = i |
| break |
| default: |
| start = i |
| break |
| } |
| } |
| |
| // final address |
| if (start !== end) { |
| list.push(header.substring(start, end)) |
| } |
| |
| return list |
| } |