An example of a reverse proxy server written using the caronte branch of node-http-proxy. I dumped node-http-proxy for nginx when it stopped supporting websockets under node 0.10.x.This version seems adequate to replace nginx again.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
var fs = require('fs'), | |
http = require('http'), | |
https = require('https'), | |
util = require('util'), | |
httpProxy = require('http-proxy'), | |
proxyTable = require('./proxy-table.js'); // proxy-table from the pre-caronte node-http-proxy | |
var routes_path = "routes.json"; | |
/* example routes.json file: | |
{ | |
"servername/term/": "127.0.0.1:8001", | |
"servername/blog/": "127.0.0.1:3000", | |
"servername/app/": "127.0.0.1:3001", | |
"servername": "127.0.0.1:81", | |
"www.domain.com/term/": "127.0.0.1:8001", | |
"www.domain.com/blog/": "127.0.0.1:3000", | |
"www.domain.com/app/": "127.0.0.1:3001", | |
"www.domain.com": "127.0.0.1:81" | |
} | |
*/ | |
var table; | |
var read_routes = function(event, filename) { | |
var routes_file = fs.readFileSync(routes_path); | |
var routes_json; | |
try { | |
routes_json = JSON.parse(routes_file); | |
} catch (err) { | |
console.log("error parsing json file"); | |
console.log("routes_file: ", routes_file); | |
console.log("routes_json: ", routes_json); | |
console.log("error was "+ err.message); | |
} | |
if (typeof(routes_json) == 'object') { | |
table = new proxyTable.ProxyTable({router: routes_json}); | |
console.log("routes: ", routes_json); | |
} else { | |
console.log("routes_json not an object: ", typeof(routes_json)); | |
} | |
} | |
read_routes(); | |
fs.watch(routes_path, {persistent: false}, read_routes); | |
// | |
// Create a proxy server with custom application logic | |
// | |
var proxy = httpProxy.createProxyServer({ | |
// turn on x-forwarded-for headers | |
xfwd : true | |
}); | |
var listener = function(req, res) { | |
console.log( req.headers.host, req.url, req.method ); | |
var target = table.getProxyLocation(req); | |
console.log( 'target: ', target ); | |
if (null != target) { | |
proxy.web(req, res, { target: target }); | |
} | |
}; | |
var https_options = { | |
key: fs.readFileSync('mykey.pem', 'utf8'), | |
cert: fs.readFileSync('mycert.pem', 'utf8'), | |
// ca: fs.readFileSync('/etc/apache2/ssl/gd_bundle.crt', 'utf8'), | |
ciphers: 'ECDHE-RSA-AES256-SHA:AES256-SHA:RC4-SHA:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM', | |
honorCipherOrder: true | |
}; | |
var server = http.createServer(listener).listen(80); | |
var httpsServer = https.createServer(https_options, listener).listen(443); | |
// Simpleminded TLS session store | |
// This leaks memory I think, in that it never forgets old sessions | |
var tlsSessionStore = {}; | |
httpsServer.on('newSession', function(id, data) { | |
console.log('NEW HTTPS session - %s', id.toString('hex')); | |
tlsSessionStore[id] = data; | |
}); | |
httpsServer.on('resumeSession', function(id, cb) { | |
console.log('RESUME HTTPS session - %s', id.toString('hex')); | |
cb(null, tlsSessionStore[id] || null); | |
}); | |
// | |
// Listen to the `upgrade` event and proxy the | |
// WebSocket requests as well. | |
// | |
var upgrade = function (req, socket, head) { | |
console.log("UPGRADE - %s", ('object' === typeof(socket.encrypted))?'https':'http') ; | |
var target = table.getProxyLocation(req); | |
if (null != target) { | |
proxy.ws(req, socket, head, {target: target}); | |
} | |
} | |
server.on('upgrade', upgrade); | |
httpsServer.on('upgrade', upgrade); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Wonderful, exactly what I'm looking for! I'll be poking at this tomorrow morning. Thanks.