http_helper/lib/brain.js

127 строки
3.4 KiB
JavaScript

var http = require('http');
var request = require('request');
var helmet = require('helmet');
var express = require('express');
var app = express();
// Messina allows for GELF logging
var messina = require('messina');
var log = messina('myapp');
/* Simple string formatting
*
* > "Hello, {0}.".fmt('Mike');
* Hello, Mike.
*/
function fmt(str, arr) {
var args = Array.prototype.slice.call(arguments, 1);
return str.replace(/\{[\w\d\._-]+\}/g, function (part) {
var index;
part = part.slice(1, -1);
index = parseInt(part, 10);
return args[index];
});
}
module.exports = function (appOptions, port) {
app.use(log.middleware({ combinedOutput: true }));
// SECURITY SETTINGS
// No xframe allowed
app.use(helmet.xframe('deny'));
// Hide that we're using Express
app.use(helmet.hidePoweredBy());
// Use XSS protection
app.use(helmet.iexss());
// A simple healthcheck endpoint for load balancers to watch
app.get('/healthcheck', function(req, res) {
res.send('healthcheck');
console.log(
fmt(
'Request to {0}://{1}/{2} returned a {3}',
req.protocol,
req.host,
req.path,
res.statusCode
)
);
});
// Any other path or route takes us to this block
app.get('*', function(req, res) {
var requestHost = req.headers.host.split(':')[0];
var hostOptions = appOptions[requestHost];
// We only want to allow http protocol
if (req.protocol !== 'http') {
console.log(fmt('{0} is not a valid protocol', req.protocol));
res.send(fmt('{0} is not a valid protocol for this app', req.protocol));
res.end();
return;
}
// We are only proxying or redirecting with GETs
if (req.method !== 'GET') {
console.log(fmt('{0} is not an acceptable method', req.method));
res.end();
return;
}
// If the host header does not have a corresponding entry in
// the config.json file, bust out.
if (!hostOptions) {
console.log(fmt('{0} is not a valid host', req.host));
res.statusCode = 404;
res.setHeader('Content-Type', 'text/plain');
res.end(fmt('{0} is invalid', req.host));
return;
}
// actionOptions dictates whether this is a proxy or redirect
var actionOptions = hostOptions.function;
// target url for redirect and proxy requests
var url = hostOptions.host + req.url;
// For requests that match a redirect host
if (actionOptions === "redirect") {
// Set the status and redirect
console.log(
fmt(
'Redirecting {0}://{1} to {2} with a http status code of {3}',
req.protocol,
req.host,
hostOptions.host,
hostOptions.code
)
);
res.statusCode = hostOptions.code || 302;
res.setHeader('Content-Type', 'text/plain');
res.setHeader('Location', url);
res.end('Redirecting to ' + url);
}
// For requests that match a proxy host
if (actionOptions === "proxy") {
request.get(url, function(error, result) {
if (error) {
res.write(
fmt(
"there was an error requesting {0}://{1}",
req.protocol,
hostOptions.host
)
);
res.write( JSON.stringify(error) );
return console.error(error);
}
console.log(fmt('Pulling {0} to {1}', url, requestHost));
res.write( result.body );
res.end();
});
}
});
app.listen(port || 80);
};