@lemonce3/mitm
Version:
HTTP/HTTPS man in the middle proxy server
61 lines (47 loc) • 1.77 kB
JavaScript
const DEFAULT_REQUEST_TIMEOUT = 2 * 60 * 1000;
module.exports = function createUpgradeHandlerFactory(websocketInterceptor, onError) {
return function upgradeHandlerFactory(shadow) {
return function upgradeHandler(clientRequest, clientSocket, head) {
const target = new URL(clientRequest.url, shadow.origin);
const proxyRequest = shadow.request({
url: target,
method: clientRequest.method,
headers: clientRequest.headers,
timeout: DEFAULT_REQUEST_TIMEOUT,
});
proxyRequest.on('error', (e) => {
onError('proxy::snd(websocket)', `<${target.origin}> - ${e.message}`);
});
proxyRequest.on('response', proxyResponse => {
// if upgrade event isn't going to happen, close the socket
if (!proxyResponse.upgrade) {
clientSocket.end();
}
});
proxyRequest.on('upgrade', (proxyResponse, proxySocket, proxyHead) => {
proxySocket.on('error', e => {
onError('upgrade', e.message);
});
clientSocket.on('error', e => {
proxySocket.end();
onError('upgrade', e.message);
});
proxySocket.setTimeout(0);
proxySocket.setNoDelay(true);
proxySocket.setKeepAlive(true, 0);
if (proxyHead && proxyHead.length) proxySocket.unshift(proxyHead);
clientSocket.write(Object.keys(proxyResponse.headers).reduce(function (head, key) {
const value = proxyResponse.headers[key];
if (Array.isArray(value)) {
value.forEach(value => head.push(`${key}: ${value}`));
} else {
head.push(`${key}: ${value}`);
}
return head;
}, ['HTTP/1.1 101 Switching Protocols']).join('\r\n') + '\r\n\r\n');
websocketInterceptor(clientSocket, proxySocket);
});
proxyRequest.end();
};
}
}