зеркало из https://github.com/mozilla/gombot.git
116 строки
3.3 KiB
JavaScript
116 строки
3.3 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
const url = require('url');
|
|
const http = require('http');
|
|
const https = require('https');
|
|
const querystring = require('querystring');
|
|
const public_url = url.parse(require('../etc/config').public_url);
|
|
|
|
var global_forward_timeout;
|
|
|
|
exports.setTimeout = function(to) {
|
|
if (typeof to !== 'number') throw 'setTimeout expects a numeric argument';
|
|
global_forward_timeout = to;
|
|
};
|
|
|
|
exports.forward = function(dest, req, res, cb) {
|
|
var _cb = cb;
|
|
var requestTimeout;
|
|
cb = function() {
|
|
if (requestTimeout) clearTimeout(requestTimeout);
|
|
if (_cb) _cb.apply(null, arguments);
|
|
};
|
|
|
|
function cleanupReq() {
|
|
if (preq) {
|
|
preq.removeAllListeners();
|
|
preq.destroy();
|
|
preq = undefined;
|
|
}
|
|
}
|
|
|
|
var u = url.parse(dest.toString());
|
|
|
|
var m = u.protocol === 'http:' ? http : https;
|
|
|
|
var preq = m.request({
|
|
host: u.hostname,
|
|
port: u.port,
|
|
path: u.path,
|
|
method: req.method,
|
|
agent: false
|
|
}, function(pres) {
|
|
|
|
res.statusCode = pres.statusCode;
|
|
|
|
// forward necessary headers
|
|
['Content-Type', 'Content-Length', 'Set-Cookie', 'Vary', 'Cache-Control', 'ETag', 'X-Frame-Options', 'Location', 'Access-Control-Allow-Origin']
|
|
.forEach(function (header) {
|
|
if (pres.headers.hasOwnProperty(header.toLowerCase())) {
|
|
res.setHeader(header, pres.headers[header.toLowerCase()]);
|
|
}
|
|
});
|
|
|
|
pres.on('data', function (chunk) {
|
|
res.write(chunk);
|
|
}).on('end', function() {
|
|
res.end();
|
|
pres.removeAllListeners();
|
|
pres.destroy();
|
|
pres = undefined;
|
|
cleanupReq();
|
|
cb();
|
|
});
|
|
}).on('error', function(e) {
|
|
cleanupReq();
|
|
cb(e);
|
|
});
|
|
|
|
if (global_forward_timeout) {
|
|
requestTimeout = setTimeout(function() { preq.destroy(); }, global_forward_timeout);
|
|
}
|
|
|
|
if (req.headers['content-type']) {
|
|
preq.setHeader('Content-Type', req.headers['content-type']);
|
|
}
|
|
|
|
// forward cookies
|
|
if (req.headers.cookie) {
|
|
preq.setHeader('Cookie', req.headers.cookie);
|
|
}
|
|
|
|
// forward header
|
|
if (req.headers['accept-language']) {
|
|
preq.setHeader('Accept-Language', req.headers['accept-language']);
|
|
}
|
|
if (req.headers['if-none-match']) {
|
|
preq.setHeader('If-None-Match', req.headers['if-none-match']);
|
|
}
|
|
if (req.headers['authorization']) {
|
|
preq.setHeader('Authorization', req.headers['authorization']);
|
|
}
|
|
|
|
// Hawk checks a single host header when generating the MAC,
|
|
// so ensure that the correct port is included when using ssl
|
|
var host = req.headers.host;
|
|
if (host.indexOf(':') < 0 && public_url.protocol === 'https:') host += ':443';
|
|
|
|
preq.setHeader('X-Forwarded-Host', host);
|
|
|
|
// if the body has already been parsed, we'll write it
|
|
if (req.body) {
|
|
var data;
|
|
if (req.headers['content-type'].indexOf('application/json') === 0) data = JSON.stringify(req.body);
|
|
else data = querystring.stringify(req.body);
|
|
preq.setHeader('content-length', Buffer.byteLength(data));
|
|
preq.write(data);
|
|
preq.end();
|
|
} else {
|
|
req.on('data', function(chunk) { preq.write(chunk); })
|
|
.on('end', function() { preq.end(); });
|
|
}
|
|
console.log('forwarding request: ' + req.url + ' -> ' + dest);
|
|
};
|