Skip to content

Commit

Permalink
Replace http-proxy with http-mitm-proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
kdzwinel committed Dec 26, 2015
1 parent 62ec181 commit 37375a7
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 63 deletions.
40 changes: 26 additions & 14 deletions lib/captured-connection.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
'use strict';

const url = require('url');
const zlib = require('zlib');
const isTextOrBinary = require('istextorbinary');
const getTime = require('./init-time');

const generateConnectionId = (() => {
let id = 1;
return () => id++;
Expand All @@ -27,25 +29,27 @@ class CapturedConnection {
this._responseBody = null;
}

setRequest(proxyReq, req) {
setRequest(req, isSSL) {
this._request = {
url: req.url,
method: proxyReq.method,
url: fullUrl(req, isSSL),
method: req.method,
headers: req.headers
};
}

setResponse(proxyRes, res) {
setResponse(res) {
this._response = {
url: res.url,
statusCode: proxyRes.statusCode,
statusMessage: proxyRes.statusMessage,
headers: adaptHeaders(proxyRes.headers),
rawHeaders: recreateRawResponseHeaders(proxyRes),
connectionId: res.connection.remotePort
statusCode: res.statusCode,
statusMessage: res.statusMessage,
headers: adaptHeaders(res.headers),
rawHeaders: recreateRawResponseHeaders(res),
connectionId: res.connection.localPort,
remoteAddress: res.connection.remoteAddress,
remotePort: res.connection.remotePort
};

this._resourceType = getResourceType(proxyRes.headers['content-type']);
this._resourceType = getResourceType(res.headers['content-type']);
}

getId() {
Expand Down Expand Up @@ -129,6 +133,14 @@ class CapturedConnection {
}
}

function fullUrl(req, isSSL) {
let parsedUrl = url.parse(req.url);
parsedUrl.protocol = isSSL ? 'https' : 'http';
parsedUrl.host = req.headers.host;

return url.format(parsedUrl);
}

//TODO should be async
function unpackBody(buffer, encoding) {
if (encoding === 'gzip') {
Expand Down Expand Up @@ -194,14 +206,14 @@ function getResourceType(contentType) {
}

//TODO try getting real raw response headers instead of this thing
function recreateRawResponseHeaders(proxyRes) {
function recreateRawResponseHeaders(res) {
let headerString = '';

for (let i = 0, l = proxyRes.rawHeaders.length; i < l; i += 2) {
headerString += proxyRes.rawHeaders[i] + ': ' + proxyRes.rawHeaders[i + 1] + '\n';
for (let i = 0, l = res.rawHeaders.length; i < l; i += 2) {
headerString += res.rawHeaders[i] + ': ' + res.rawHeaders[i + 1] + '\n';
}

return `HTTP/${proxyRes.httpVersion} ${proxyRes.statusCode} ${proxyRes.statusMessage}
return `HTTP/${res.httpVersion} ${res.statusCode} ${res.statusMessage}
${headerString}`;
}

Expand Down
4 changes: 2 additions & 2 deletions lib/rdp-message-formatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ function responseReceived(connection) {
receiveHeadersEnd: (connection.getTiming().responseReceived - connection.getTiming().start) * 1000
},
requestHeaders: connection.getRequest().headers,
remoteIPAddress: '127.0.0.1',
remotePort: 80
remoteIPAddress: response.remoteAddress,
remotePort: response.remotePort
}
};
}
Expand Down
73 changes: 29 additions & 44 deletions lib/traffic-interceptor.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
'use strict';

const http = require('http');
const httpProxy = require('http-proxy');
const url = require('url');
const MITMProxy = require('http-mitm-proxy');
const EventEmitter = require('events');
const Agent = require('agentkeepalive');
const CapturedConnection = require('./captured-connection');
const getTime = require('./init-time');

Expand All @@ -18,53 +15,41 @@ class TrafficInterceptor extends EventEmitter {
//TODO we never remove requests from here - see #8
this._connections = new Map();

let agent = new Agent({
keepAlive: true
});
let proxy = new MITMProxy();

this._proxy = httpProxy.createProxyServer({agent})
.on('proxyReq', handleIncomingRequest.bind(this))
.on('proxyRes', handleIncomingResponse.bind(this))
.on('error', handleProxyError.bind(this));
proxy.onRequest(handleIncomingRequest.bind(this));
proxy.onResponse(handleIncomingResponse.bind(this));
proxy.onError(handleProxyError.bind(this));

this._server = http.createServer(handleHTTPRequest.bind(this))
.on('error', (error) => {
this.emit('error', error);
})
.listen(port);
proxy.listen({port: port});
}

getConnection(id) {
return this._connections.get(id);
}
}

function handleHTTPRequest(req, res) {
this.emit('log', 'Request recorded: ' + req.method + ' ' + req.url);

let target = url.parse(req.url);

this._proxy.web(req, res, {
target: target.protocol + '//' + target.host
});
}

function handleIncomingRequest(proxyReq, req, res, options) {
function handleIncomingRequest(ctx, callback) {
let connection = new CapturedConnection();
connection.setRequest(proxyReq, req);
connection.setRequest(ctx.clientToProxyRequest, ctx.isSSL);

this._connections.set(connection.getId(), connection);
req.log = {
ctx.log = {
id: connection.getId()
};

this.emit('request', connection);

return callback();
}

function handleIncomingResponse(proxyRes, req, res) {
this.emit('log', 'Response arrived: ' + req.method + ' ' + req.url + ' ' + res.statusCode);
function handleIncomingResponse(ctx, callback) {
let request = ctx.clientToProxyRequest;
let response = ctx.serverToProxyResponse;

this.emit('log', 'Response arrived: ' + request.method + ' ' + request.url + ' ' + response.statusCode);

let connectionId = req.log && req.log.id;
let connectionId = ctx.log && ctx.log.id;
let connection = null;

if (connectionId) {
Expand All @@ -76,27 +61,23 @@ function handleIncomingResponse(proxyRes, req, res) {
return;
}

connection.setResponse(proxyRes, res);
connection.setResponse(response);
connection.registerResponseReceived();
this.emit('response-received', connection);

let _end = res.end;
let _write = res.write;
let trafficInterceptor = this;

res.write = function(chunk) {
_write.apply(res, arguments);
ctx.onResponseData(function(ctx, chunk, callback) {
connection.registerDataReceived(chunk);

trafficInterceptor.emit('response-data', connection, {
time: getTime,
time: getTime(),
encodedLength: chunk.length
});
};

res.end = function() {
_end.apply(res, arguments);

return callback(null, chunk);
});
ctx.onResponseEnd(function(ctx, callback) {
connection.registerResponseFinished();

//after whole body was received and unpacked we can push its size to the front-end
Expand All @@ -107,10 +88,14 @@ function handleIncomingResponse(proxyRes, req, res) {
});

trafficInterceptor.emit('response-finished', connection);
};

return callback();
});

return callback();
}

function handleProxyError(error) {
function handleProxyError(ctx, error) {
this.emit('error', 'Proxy error:', error);
}

Expand Down
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@
"dependencies": {
"agentkeepalive": "^2.0.3",
"chalk": "^1.1.1",
"http-mitm-proxy": "^0.2.0",
"http-proxy": "^1.12.0",
"istextorbinary": "^1.0.2"
"http-mitm-proxy": "^0.2.0"
},
"devDependencies": {
"electron-packager": "^5.1.1",
Expand Down

0 comments on commit 37375a7

Please sign in to comment.