зеркало из https://github.com/mozilla/http_helper.git
127 строки
3.4 KiB
JavaScript
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);
|
|
};
|