|
"use strict"; |
|
|
|
/* |
|
|
|
Creates a HTTP proxy that rewrites Host: header to a predefined value |
|
Useful when forwarding requests to Apache or Nginx virtual hosts |
|
|
|
Usage: |
|
|
|
PORT_LISTEN=123 PORT_TARGET=456 HOST_TARGET=127.0.0.1 HOST_ORIGIN="tere.ee" node proxy.js |
|
|
|
Where |
|
|
|
* PORT_LISTEN is the port the proxy should be listening for incoming requests |
|
* PORT_TARGET is the port the target server is listening for |
|
* HOST_TARGET is the hostname or IP where the target server is listening on |
|
* HOST_ORIGIN is the value that is set for the Host: header |
|
|
|
and optionally |
|
|
|
* LOG_REQUESTS turns request logging to the console on/off (default on; "Y", "yes", "1", |
|
or "true" enable logging, anything else disables it) |
|
|
|
*/ |
|
|
|
var http = require("http"), |
|
url = require("url"); |
|
|
|
var listenPort = process.env.PORT_LISTEN || 8080, |
|
targetPort = process.env.PORT_TARGET || 9000, |
|
targetHost = process.env.HOST_TARGET || "localhost", |
|
origin = process.env.HOST_ORIGIN || "origin", |
|
lcorigin = origin.toLowerCase(), |
|
logRequests = !!(process.env.LOG_REQUESTS || "Y").toUpperCase().match(/^(?:y|yes|1|true)$/i); |
|
|
|
var server = http.createServer(function(request, response){ |
|
var options, proxyRequest, user, requestHost; |
|
|
|
requestHost = request.headers.host; |
|
request.headers.host = origin; |
|
request.headers['x-forwarded-for'] = request.headers['x-forwarded-for'] || request.connection.remoteAddress; |
|
|
|
options = url.parse("http://" + targetHost+(targetPort?":"+targetPort:"") + request.url); |
|
options.method = request.method; |
|
options.headers = request.headers; |
|
|
|
proxyRequest = http.request(options); |
|
|
|
proxyRequest.addListener("response", function (proxyResponse) { |
|
|
|
handleResponse(requestHost, proxyResponse, response); |
|
|
|
// Log requests to console |
|
if (logRequests) { |
|
console.log("%s [%s] \"%s %s\" %s", |
|
request.headers['x-forwarded-for'], |
|
new Date().toISOString().replace(/T/, " ").replace(/\.\d+Z/i, ""), |
|
request.method, |
|
request.url, |
|
proxyResponse.statusCode); |
|
} |
|
}); |
|
|
|
request.pipe(proxyRequest); |
|
}); |
|
|
|
function handleResponse(requestHost, proxyResponse, response) { |
|
var headers; |
|
|
|
// Rewrite location headers for 3xx responses |
|
if (proxyResponse.statusCode >= 300 && proxyResponse.statusCode <= 399) { |
|
headers = {}; |
|
Object.keys(proxyResponse.headers).forEach(function(name) { |
|
var value = proxyResponse.headers[name]; |
|
var location; |
|
if (name.toLowerCase() === 'location') { |
|
location = url.parse(value); |
|
if (location && location.hostname) { |
|
if (location.hostname.toLowerCase() === lcorigin) { |
|
location.hostname = requestHost; |
|
delete location.host; |
|
value = url.format(location); |
|
} |
|
} |
|
} |
|
headers[name] = value; |
|
}); |
|
} |
|
else { |
|
headers = proxyResponse.headers; |
|
} |
|
response.writeHead(proxyResponse.statusCode, headers); |
|
|
|
proxyResponse.pipe(response); |
|
} |
|
|
|
server.listen(listenPort, function(){ |
|
console.log("Proxy listening on port %s", listenPort); |
|
console.log("Forwarding requests to http://%s as %s", targetHost+(targetPort?":"+targetPort:""), origin); |
|
}); |