Express is awesome. Yet there's one thing that annoys me: retrieving the IP address of a request.
Yeah I know. You can grab it with req.connection.remoteAddress.
But what if the request was sent via a proxy? Express has a solution for this, too:
app.set("trust proxy", true);
// ...
console.log(req.ips); // ["proxy-n", "proxy-2", "proxy-1", "client"]
But here's already the first flaw: req.ips only works if the client uses a proxy. If the client doesn't use a proxy you'd have to check that first and then fall back to req.connection.remoteAddress.
"This is shit. Change that." — Co-worker.
But wait, it gets even worse. Let's say I use http-proxy. So http-proxy send all the client's requests to my nice little express app and is so kind to add an x-forwarded-for header with the client's IP. console.log(req.ips); would return ["clientIP"], which is fine.
After half a year of testing and development on my http-proxyied testserver I want to move on to my production server. Without http-proxy.
Well, shit. req.ips is now empty and I'd have to use req.connection.remoteAddress everywhere where I used req.ips, which would be a lot of changing an reviewing.
I suggest, that req.ip (without plural-s) should always return a string either containing the req.connection.remoteAddress or if available and allowed by app.set("trust proxy", true); the last IP address (aka the client's IP).
req.ips wouldn't have to be altered.
/**
* If "trust proxy" is `true`, parse
* the "X-Forwarded-For" ip address list
* and return the last ip address (the client's ip).
*
* If not, return req.connection.remoteAddress.
*
* @return {String}
* @api public
*/
req.__defineGetter__('ip', function(){
var trustProxy = this.app.get('trust proxy');
return trustProxy ? (this.ips.reverse()[0] || this.connection.remoteAddress) : this.connection.remoteAddress;
});
By the way: You have a security failure in req.ips. According to your specification it should contain a trustProxy check, like so:
req.__defineGetter__('ips', function(){
var trustProxy = this.app.get('trust proxy');
var val = this.get('X-Forwarded-For');
return trustProxy && val
? val.split(/ *, */).reverse()
: [];
});
Greetings,
Jan