UNPKG

sundry

Version:

A dynamically configurable, load balancing, reverse proxy.

177 lines (150 loc) 5.18 kB
var http = require('http'); var https = require('https'); var _ = require('lodash'); var url = require('url'); var env = require('./../Configuration/configLoader').loadedConfig; var logger = require('./../logger').logger; var path = require('path'); var fs = require('fs'); var Cookies = require('cookies'); var NODE_ENV = (env.NODE_ENV === 'production'); //var PluginManager = require('./../Plugins'); // //PluginManager.register(function(req, next){ // console.log('run first'); // next(); // //}); //PluginManager.register(function(req, next){ // next(); //}); var httpProxy = require('http-proxy'); var staticPages = require('./defaultFiles'); var incomingProtocol = env.sundry_redirect_ssl ? "https://" : "http://" var proxy = httpProxy.createProxyServer(); var handleWebProxy = function(req, res, proxyTo){ return proxy.web(req, res, { xfwd: true, target: { host: proxyTo.host, port: proxyTo.port } }, function(err){ console.log(err); res.writeHead(503); res.write(staticPages.five); res.end(); }); }; /** * Handler function for default address. * Returns a function to either proxy to a default * application, or to write the index.html page. */ var handleDefaultAddress = (function(){ if(env.sundry_default_application){ return function(req, res){ handleWebProxy(req, res, env.sundry_default_application) } } return function(req, res){ res.writeHead(200,{'Content-Type': 'text/html'}); res.write(staticPages.index) res.end() } })() module.exports = function(serverOptions, Router) { /** * Main Proxy handler */ var stickyBalanceProxy = function(req, res){ var parsedHeader = url.parse(incomingProtocol + req.headers.host).hostname; //Return early if this route matches the default set in the config. if(parsedHeader === env.sundry_default_address) { return handleDefaultAddress(req, res) } var cookie = new Cookies(req, res, env.sundry_sticky_cookie_secret) //Send our request host data to the Router to be looked up and cached if found. Router.findRoute(parsedHeader, cookie.get('stickyRoute'), function proxyRequest(data) { if(data) { cookie.set('stickyRoute', data.identity, {signed: true}) return handleWebProxy(req, res, data) } else { res.writeHead(404, {'Content-Type': 'text/html'}); res.write(staticPages.four) res.end() } }) } var roundBalanceProxy = function(req, res) { var parsedHeader = url.parse(incomingProtocol + req.headers.host).hostname; //Return early if this route matches the default set in the config. if(parsedHeader === env.sundry_default_address) { return handleDefaultAddress(req, res) } //Send our request host data to the Router to be looked up and cached if found. Router.findRoute(parsedHeader, null, function proxyRequest(data) { if(data) { return handleWebProxy(req, res, data) } else { res.writeHead(404, {'Content-Type': 'text/html'}); res.write(staticPages.four) res.end() } }) }; var proxyRoute = (env.sundry_sticky) ? stickyBalanceProxy : roundBalanceProxy /* * Handle http -> https redirects differently based on the current env. */ var redirect = { production: function(req, res) { res.writeHead(301, {Location: 'https://' + req.headers.host + req.url}); res.end() }, development: function(req, res){ var host = req.headers.host.split(':'); host[host.length - 1] = env.sundry_dev_ssl_port; host = host.join(':'); res.writeHead(301, {Location: 'https://' + host + req.url}); res.end(); } }; /* * Handler for dev/test response server. */ var testHandler = function(req, res){ var parsed = url.parse(req.url) res.setHeader('content-type', 'text/html'); res.writeHead(200); res.write('<!DOCTYPE html>'); res.write('<html><head><title>Sundry Test Server</title></head><body>'); res.write('<h1>Backend Server - '+ req.socket.localAddress + ':' + req.socket.localPort +'</h1>') res.write('<h3>Host - ' + req.headers.host + '</h3>') res.write('<h3>URL - ' + parsed.pathname + '</h3>') res.write('<h3>Query - ' + parsed.query + '</h3>') res.write('</body></html>'); res.end(); }; /* * Return a group of servers dependant on options and env. * at a bare minimum this will provide a server to 301 redirect http requests * to https, as well as our dynamic reverse proxying server over https. * * It will optionally return a server to test and develop against locally. */ var serverGroup = {}; if(env.sundry_redirect_ssl) { var handleRedirect = NODE_ENV ? redirect.production : redirect.development; serverGroup.http = http.createServer(handleRedirect); serverGroup.https = https.createServer(serverOptions.tlsOptions, proxyRoute); } else { serverGroup.http = http.createServer(proxyRoute); } if(!NODE_ENV){ _.extend(serverGroup, {test: http.createServer(testHandler), test2: http.createServer(testHandler)}); } return serverGroup; };