Skip to content

Commit eacb598

Browse files
committed
Added option to get TX/RX statistics from handlers
1 parent 0f46f3b commit eacb598

File tree

6 files changed

+68
-10
lines changed

6 files changed

+68
-10
lines changed

Diff for: .editorconfig

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 4
6+
charset = utf-8
7+
trim_trailing_whitespace = true
8+
insert_final_newline = true
9+
end_of_line = lf
10+
# editorconfig-tools is unable to ignore longs strings or urls
11+
max_line_length = null

Diff for: src/handler_base.js

+9
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,15 @@ export default class HandlerBase extends EventEmitter {
170170
}
171171
}
172172

173+
getStatistics() {
174+
return {
175+
srcTxBytes: this.srcSocket ? this.srcSocket.bytesWritten : undefined,
176+
srcRxBytes: this.srcSocket ? this.srcSocket.bytesRead : undefined,
177+
trgTxBytes: this.trgSocket ? this.trgSocket.bytesWritten : undefined,
178+
trgRxBytes: this.trgSocket ? this.trgSocket.bytesRead : undefined,
179+
};
180+
}
181+
173182
/**
174183
* Detaches all listeners and destroys all sockets.
175184
*/

Diff for: src/handler_forward.js

+2
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ export default class HandlerForward extends HandlerBase {
115115
this.trgRequest.on('socket', (socket) => {
116116
this.log('Target socket assigned');
117117

118+
this.trgSocket = socket;
119+
118120
socket.once('close', () => {
119121
this.log('Target socket closed');
120122
});

Diff for: src/server.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ export class Server extends EventEmitter {
131131
*/
132132
onConnect(request) {
133133
this.log(`${request.method} ${request.url} HTTP/${request.httpVersion}`);
134-
// console.dir(request.headers);
135134

136135
this.prepareRequestHandling(request)
137136
.then((handlerOpts) => {
@@ -209,6 +208,7 @@ export class Server extends EventEmitter {
209208
socket.pause();
210209

211210
const funcOpts = {
211+
handlerId: result.id,
212212
request,
213213
username: null,
214214
password: null,
@@ -256,6 +256,7 @@ export class Server extends EventEmitter {
256256
handler.once('destroy', () => {
257257
delete this.handlers[handler.id];
258258
});
259+
259260
handler.run();
260261
}
261262

@@ -357,6 +358,18 @@ export class Server extends EventEmitter {
357358
.nodeify(callback);
358359
}
359360

361+
362+
/**
363+
* Calls handler by ID and reads it's usage statistics.
364+
* @return {Object} statistics { srcTxBytes, srcRxBytes, trgTxBytes, trgRxBytes }
365+
*/
366+
getStatisticsForHandler(handlerId) {
367+
const handler = this.handlers && this.handlers[handlerId];
368+
if (!handler) return undefined;
369+
370+
return handler.getStatistics();
371+
}
372+
360373
/**
361374
* Closes the proxy server.
362375
* @param [closeConnections] If true, then all the pending connections from clients

Diff for: test/anonymize_proxy.js

+2-5
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ before(() => {
6767
app.listen(testServerPort, (err) => {
6868
if (err) reject(err);
6969
resolve();
70-
})
70+
});
7171
});
72-
})
72+
});
7373
});
7474

7575
after(function () {
@@ -85,9 +85,6 @@ const requestPromised = (opts) => {
8585
request(opts, (error, response, body) => {
8686
if (error) return reject(error);
8787
if (response.statusCode !== 200) {
88-
//console.log('ERROR VOLE');
89-
// console.dir(response);
90-
//console.dir(body);
9188
return reject(new Error(`Received invalid response code: ${response.statusCode}`));
9289
}
9390
if (opts.expectBodyContainsText) expect(body).to.contain(opts.expectBodyContainsText);

Diff for: test/server.js

+30-4
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ const createTestSuite = ({
114114
let upstreamProxyRequestCount = 0;
115115

116116
let mainProxyServer;
117+
let mainProxyServerStatisticsInterval;
118+
const mainProxyServerHandlers = {};
117119
let mainProxyServerPort;
118120
const mainProxyRequestCount = 0;
119121

@@ -198,7 +200,7 @@ const createTestSuite = ({
198200

199201
if (mainProxyAuth || useUpstreamProxy) {
200202
opts.prepareRequestFunction = ({
201-
request, username, password, hostname, port, isHttp,
203+
request, username, password, hostname, port, isHttp, handlerId
202204
}) => {
203205
const result = {
204206
requestAuthentication: false,
@@ -245,6 +247,12 @@ const createTestSuite = ({
245247
result.upstreamProxyUrl = upstreamProxyUrl;
246248
}
247249

250+
mainProxyServerHandlers[handlerId] = {
251+
groups: username ? username.replace('groups-', '').split('+') : [],
252+
token: password,
253+
hostname,
254+
};
255+
248256
// Sometimes return a promise, sometimes the result directly
249257
if (counter++ % 2 === 0) return result;
250258
return Promise.resolve(result);
@@ -275,7 +283,6 @@ const createTestSuite = ({
275283
// Tests for 502 Bad gateway or 407 Proxy Authenticate
276284
// Unfortunately the request library throws for HTTPS and sends status code for HTTP
277285
const testForErrorResponse = (opts, expectedStatusCode) => {
278-
279286
let requestError = null;
280287
const onRequestFailed = (err) => {
281288
requestError = err;
@@ -433,10 +440,29 @@ const createTestSuite = ({
433440
.then((response) => {
434441
expect(response.body).to.match(/^a{1000000}$/);
435442
expect(response.statusCode).to.eql(200);
443+
const expectedSize = 1000000; // "a" takes one byte, so one 1 milion "a" should be 1MB
444+
445+
// this if is here because some tests do not use prepareRequestFunction and therefore are not
446+
// trackable
447+
if (mainProxyServerHandlers && Object.keys(mainProxyServerHandlers).length) {
448+
const sortedIds = Object.keys(mainProxyServerHandlers).sort((a, b) => {
449+
if (Number(a) < Number(b)) return -1;
450+
if (Number(a) > Number(b)) return 1;
451+
return 0;
452+
});
453+
const lastHandler = sortedIds[sortedIds.length - 1];
454+
const stats = mainProxyServer.getStatisticsForHandler(lastHandler);
455+
456+
// 5% range because network negotiation adds to network trafic
457+
expect(stats.srcTxBytes).to.be.within(expectedSize, expectedSize * 1.05);
458+
expect(stats.trgRxBytes).to.be.within(expectedSize, expectedSize * 1.05);
459+
}
436460
});
437461
};
438462
_it('handles large GET response', test1MAChars);
439-
_it('handles large streamed GET response', test1MAChars);
463+
464+
// TODO: Test streamed GET
465+
// _it('handles large streamed GET response', test1MAChars);
440466

441467
_it('handles 301 redirect', () => {
442468
const opts = getRequestOpts('/redirect-to-hello-world');
@@ -632,6 +658,7 @@ const createTestSuite = ({
632658

633659
after(function () {
634660
this.timeout(2 * 1000);
661+
if (mainProxyServerStatisticsInterval) clearInterval(mainProxyServerStatisticsInterval);
635662

636663
// Shutdown all servers
637664
return Promise.resolve().then(() => {
@@ -735,4 +762,3 @@ useSslVariants.forEach((useSsl) => {
735762
});
736763
});
737764
});
738-

0 commit comments

Comments
 (0)