bricks-cli
Version:
Command line tool for developing ambitious ember.js apps
100 lines (83 loc) • 2.74 kB
JavaScript
var owns = {}.hasOwnProperty;
module.exports = function proxyMiddleware(options) {
var httpLib = options.protocol === 'https:' ? 'https' : 'http';
var request = require(httpLib).request;
options = options || {};
options.hostname = options.hostname;
options.port = options.port;
return function (req, resp, next) {
var url = req.url;
// You can pass the route within the options, as well
if (typeof options.route === 'string') {
var route = slashJoin(options.route, '');
if (url.slice(0, route.length) === route) {
url = url.slice(route.length);
} else {
return next();
}
}
//options for this request
var opts = extend({}, options);
opts.path = slashJoin(options.pathname, url);
opts.method = req.method;
opts.headers = options.headers ? merge(req.headers, options.headers) : req.headers;
applyViaHeader(req.headers, opts, opts.headers);
// Forwarding the host breaks dotcloud
delete opts.headers["host"];
var myReq = request(opts, function (myRes) {
var statusCode = myRes.statusCode
, headers = myRes.headers
, location = headers.location;
// Fix the location
if (statusCode > 300 && statusCode < 304 && location.indexOf(options.href) > -1) {
// absoulte path
headers.location = location.replace(options.href, slashJoin('', slashJoin((options.route || ''), '')));
}
applyViaHeader(myRes.headers, opts, myRes.headers);
resp.writeHead(myRes.statusCode, myRes.headers);
myRes.on('error', function (err) {
next(err);
});
myRes.pipe(resp);
});
myReq.on('error', function (err) {
next(err);
});
if (!req.readable) {
myReq.end();
} else {
req.pipe(myReq);
}
};
};
function applyViaHeader(existingHeaders, opts, applyTo) {
if(!opts.via) {
return;
}
var viaName = (true === opts.via) ?
// use the host name
require('os').hostname() :
// or use whatever was passed as the options.via value
opts.via;
var viaHeader = '1.1 ' + viaName;
if(existingHeaders.via) {
viaHeader = existingHeaders.via + ', ' + viaHeader;
}
applyTo.via = viaHeader;
}
function slashJoin(p1, p2) {
if (p1.length && p1[p1.length - 1] === '/') {p1 = p1.substring(0, p1.length - 1); }
if (p2.length && p2[0] === '/') {p2 = p2.substring(1); }
return p1 + '/' + p2;
}
function extend(obj, src) {
for (var key in src) if (owns.call(src, key)) obj[key] = src[key];
return obj;
}
//merges data without changing state in either argument
function merge(src1, src2) {
var merged = {};
extend(merged, src1);
extend(merged, src2);
return merged;
}