Skip to content

Instantly share code, notes, and snippets.

@mhseiden
Created April 10, 2012 00:39
Show Gist options
  • Save mhseiden/2347637 to your computer and use it in GitHub Desktop.
Save mhseiden/2347637 to your computer and use it in GitHub Desktop.
Lightweight "node-http-proxy" HTTP/WS Proxy Server
// Node Modules
////////////////////////////////////////////////////////////////////////////////
var http_m = require("http");
// 3rd Party Modules
////////////////////////////////////////////////////////////////////////////////
var http_proxy_m = require("http-proxy");
// Utilities
////////////////////////////////////////////////////////////////////////////////
var cookie_parser = function(cookies_, name)
{
var compare = new RegExp(name+"=\\d+;?", "g")
, cookies = cookies_ || ""
, result;
if(result = cookies.match(compare)) {
return result[0].replace(name+"=", "");
} else {
return undefined;
}
}
var attach_cookie = function(res, cookie)
{
res.setHeader("set-cookie", cookie.k+"="+cookie.v+"; path=/; HttpOnly;");
}
// Web Socket Configs
////////////////////////////////////////////////////////////////////////////////
// In-Memory cookie-to-proxy cache
var ws_cookies = {};
// Array of proxy nodes
var ws_nodes = [
{host: "127.0.0.1", port: 8001}
, {host: "127.0.0.1", port: 8002}
// On creation, map the pairs to new HttpProxy objects
].map(function(pair) {return new http_proxy_m.HttpProxy({target: pair});});
var handle_ws = function(req, res)
{
// Parse the request for a ws session cookie
var cookie = cookie_parser(req.headers.cookie, "ws");
// Handles cookie creation and attachment
if(!cookie) {
cookie = Math.floor(Math.random()*9999999999999);
attach_cookie(res, {k: "ws", v: cookie});
}
// Handle cookie => proxy association
if(!ws_cookies[cookie]) {
var proxy = ws_nodes.shift()
ws_cookies[cookie] = proxy;
ws_nodes.push(proxy);
}
// init proxy
ws_cookies[cookie].proxyRequest(req, res);
}
// This handler is attached to the proxy server (see below)
var handle_ws_upgrade = function(req, socket, head)
{
// Since the socket.io handshake begins with HTTP,
// we can assume there is a cookie (and return if there isn't)
var cookie = cookie_parser(req.headers.cookie, "ws");
if(!cookie) {return;}
ws_cookies[cookie].proxyWebSocketRequest(req, socket, head);
console.log("WebSocket client on", ws_cookies[cookie].target.port);
}
// REST API Configs
////////////////////////////////////////////////////////////////////////////////
var api_cookies = {};
var api_nodes = [
{host: "127.0.0.1", port: 9001}
, {host: "127.0.0.1", port: 9002}
// On creation, map the pairs to new HttpProxy objecs
].map(function(pair) {return new http_proxy_m.HttpProxy({target: pair});});
var handle_api = function(req, res)
{
var proxy = api_nodes.shift();
proxy.proxyRequest(req, res);
api_nodes.push(proxy);
console.log("HTTP client on", proxy.target.port);
}
// Error Configs
////////////////////////////////////////////////////////////////////////////////
var handle_error = function(req, res) {res.end();}
// Proxy Server Configs
////////////////////////////////////////////////////////////////////////////////
var server = http_m.createServer(function(req, res) {
switch(req.headers.host) {
case "ws.app.com":
handle_ws(req, res);
break;
case "api.app.com":
handle_api(req, res);
break;
default:
handle_error(req, res);
break;
}
});
server.on("upgrade", handle_ws_upgrade);
server.listen(80);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment