89 lines
1.5 KiB
JavaScript
89 lines
1.5 KiB
JavaScript
/*!
|
|
* 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 = getSocketAddr(req);
|
|
var addrs = [socketAddr].concat(proxyAddrs);
|
|
|
|
// return all addresses
|
|
return addrs;
|
|
}
|
|
|
|
/**
|
|
* Get the socket address for a request.
|
|
*
|
|
* @param {object} req
|
|
* @return {string}
|
|
* @private
|
|
*/
|
|
|
|
function getSocketAddr(req) {
|
|
return req.socket ? req.socket.remoteAddress : req.connection.remoteAddress;
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|