Created
December 28, 2012 08:28
-
-
Save takeshy/4395859 to your computer and use it in GitHub Desktop.
http-proxyを使ったWebSocket対応のreverse proxy。 proxy先のHostの情報のJSONファイルを監視していて、変更があれば読み込むようになっているため動的にproxy先のサーバを変更できる。死活監視プログラムがJSONを作成すればFailOverが実現できる。
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
var http = require('http') | |
, httpProxy = require('http-proxy') | |
, Cookie = require('cookie') | |
, fs = require('fs'); | |
var SERVERS_FILE_NAME = "servers.json" | |
var PROXY_PORT = 4000 | |
var SERVERS = null; | |
var g_httpProxies = {}; | |
function readValidServersInfo(){ | |
fs.readFile(SERVERS_FILE_NAME,function(err,data){ | |
try{ | |
if(err) throw err; | |
currentServers = JSON.parse(data); | |
if(currentServers.length == 0) throw new Error("valid server was not existed."); | |
SERVERS = currentServers; | |
console.log(SERVERS); | |
}catch(e){ | |
console.log(e); | |
if(SERVERS == null){ | |
exit(); | |
} | |
} | |
}); | |
} | |
function decideHost(){ | |
var idx = Math.floor(Math.random() * SERVERS.length); | |
return {key: idx + ":" + SERVERS[idx].host + SERVERS[idx].port,host: SERVERS[idx].host,port: SERVERS[idx].port}; | |
} | |
function decideHostFromKey(key){ | |
var sPos = key.indexOf(":"); | |
if(sPos == -1){ | |
return decideHost(); | |
} | |
var index = key.substr(0,sPos); | |
var serverWithPort = key.substr(sPos + 1,key.length - sPos - 1); | |
var serverInfo = SERVERS[index]; | |
if(serverInfo && (serverInfo.host + serverInfo.port) == serverWithPort){ | |
return {key: key,host: serverInfo.host,port: serverInfo.port}; | |
}else{ | |
SERVERS.forEach(function(server){ | |
if((server.host + server.port) == serverWithPort){ | |
return {key: key,host: server.host,port: server.port}; | |
} | |
}); | |
} | |
return decideHost(); | |
} | |
function getProxyInfo(req){ | |
var target,cookie; | |
if(req.headers.cookie){ | |
cookie = Cookie.parse(req.headers.cookie); | |
if(cookie && cookie.proxyKey){ | |
return decideHostFromKey(cookie.proxyKey); | |
} | |
} | |
return decideHost(); | |
} | |
function findOrCreateHttpProxy(req,res){ | |
var proxyInfo = getProxyInfo(req); | |
if(res){ | |
res.setHeader('Set-Cookie', 'proxyKey=' + proxyInfo.key); | |
} | |
if(! g_httpProxies[proxyInfo.key]){ | |
g_httpProxies[proxyInfo.key] = new httpProxy.HttpProxy({target: { host: proxyInfo.host ,port: proxyInfo.port }}); | |
} | |
return g_httpProxies[proxyInfo.key]; | |
} | |
readValidServersInfo(); | |
fs.watchFile(SERVERS_FILE_NAME,function(curr,filename){ | |
readValidServersInfo(); | |
}); | |
var server = http.createServer(function(req,res){ | |
var proxy = findOrCreateHttpProxy(req,res); | |
proxy.proxyRequest(req,res); | |
}); | |
server.on('upgrade',function(req,socket,head){ | |
var proxy = findOrCreateHttpProxy(req); | |
proxy.proxyWebSocketRequest(req,socket,head); | |
}); | |
server.listen(PROXY_PORT); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment