description and source-codefunction proxy(host, options) {
assert(host, 'Host should not be empty');
options = options || {};
var parsedHost;
var intercept = options.intercept;
var decorateRequest = options.decorateRequest;
var forwardPath = options.forwardPath || defaultForwardPath;
var resolveProxyPathAsync = options.forwardPathAsync || defaultForwardPathAsync(forwardPath);
var filter = options.filter || defaultFilter;
var limit = options.limit || '1mb';
var preserveReqSession = options.preserveReqSession;
var memoizeHost = unset(options.memoizeHost) ? true : options.memoizeHost;
return function handleProxy(req, res, next) {
if (!filter(req, res)) { return next(); }
var resolvePath = resolveProxyPathAsync(req, res);
var parseBody = maybeParseBody(req, limit);
var prepareRequest = Promise.all([resolvePath, parseBody]);
prepareRequest.then(function(results) {
var path = results[0];
var bodyContent = results[1];
sendProxyRequest(req, res, next, path, bodyContent);
});
};
function sendProxyRequest(req, res, next, path, bodyContent) {
parsedHost = (memoizeHost && parsedHost) ? parsedHost : parseHost(host, req, options);
var reqOpt = {
hostname: parsedHost.host,
port: options.port || parsedHost.port,
headers: reqHeaders(req, options),
method: req.method,
path: path,
bodyContent: bodyContent,
params: req.params,
};
if (preserveReqSession) {
reqOpt.session = req.session;
}
if (decorateRequest) {
reqOpt = decorateRequest(reqOpt, req) || reqOpt;
}
bodyContent = reqOpt.bodyContent;
delete reqOpt.bodyContent;
delete reqOpt.params;
bodyContent = options.reqAsBuffer ?
asBuffer(bodyContent, options) :
asBufferOrString(bodyContent);
reqOpt.headers['content-length'] = getContentLength(bodyContent);
if (bodyEncoding(options)) {
reqOpt.headers['Accept-Charset'] = bodyEncoding(options);
}
function postIntercept(res, next, rspData) {
return function(err, rspd, sent) {
if (err) {
return next(err);
}
rspd = asBuffer(rspd, options);
rspd = maybeZipResponse(rspd, res);
if (!Buffer.isBuffer(rspd)) {
next(new Error('intercept should return string or' +
'buffer as data'));
}
if (!res.headersSent) {
res.set('content-length', rspd.length);
} else if (rspd.length !== rspData.length) {
var error = '"Content-Length" is already sent,' +
'the length of response data can not be changed';
next(new Error(error));
}
if (!sent) {
res.send(rspd);
}
};
}
var proxyTargetRequest = parsedHost.module.request(reqOpt, function(rsp) {
var chunks = [];
rsp.on('data', function(chunk) {
chunks.push(chunk);
});
rsp.on('end', function() {
var rspData = Buffer.concat(chunks, chunkLength(chunks));
if (intercept) {
rspData = maybeUnzipResponse(rspData, res);
var callback = postIntercept(res, next, rspData);
intercept(rsp, rspData, req, res, callback);
} else {
// see issue https://github.com/villadora/express-http-proxy/issues/104
// Not sure how to automate tests on this line, so be careful when changing.
if (!res.headersSent) {
res.send(rspData);
}
}
});
rsp.on('error', function(err) {
next(err);
});
if (!res.headersSent) {
res.status(rsp.statusCode);
Object.keys(rsp.headers)
.filter(function(item) { return item !== 'transfer-encoding'; })
.forEach(function(item) {
res.set(item, rsp.headers[item]);
});
}
});
proxyTargetRequest.on('socket', function(socket) {
if (options.timeout) {
socket.setTimeout(options.timeout, function( ...