Skip to content

Commit b616b51

Browse files
authored
fixed content_length and status always ints (#402)
1 parent c369dde commit b616b51

File tree

8 files changed

+90
-10
lines changed

8 files changed

+90
-10
lines changed

packages/core/lib/middleware/incoming_request_data.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
var { getHttpResponseData } = require('../segments/segment_utils');
12

23
/**
34
* Represents an incoming HTTP/HTTPS call.
@@ -49,12 +50,7 @@ var getClientIp = function getClientIp(req) {
4950
*/
5051

5152
IncomingRequestData.prototype.close = function close(res) {
52-
this.response = {
53-
status: res.statusCode || ''
54-
};
55-
56-
if (res.headers && res.headers['content-length'])
57-
this.response.content_length = res.headers['content-length'];
53+
this.response = getHttpResponseData(res);
5854
};
5955

6056
module.exports = IncomingRequestData;

packages/core/lib/segments/attributes/remote_request_data.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const { getHttpResponseData } = require('../segment_utils');
12
var { stripQueryStringFromPath } = require('../../utils');
23

34
/**
@@ -23,10 +24,7 @@ RemoteRequestData.prototype.init = function init(req, res, downstreamXRayEnabled
2324
}
2425

2526
if (res) {
26-
this.response = {
27-
status: res.statusCode || '',
28-
content_length: (res.headers && res.headers['content-length']) ? res.headers['content-length'] : 0
29-
};
27+
this.response = getHttpResponseData(res);
3028
}
3129
};
3230

packages/core/lib/segments/segment_utils.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import * as http from 'http';
2+
13
export const streamingThreshold: number;
24

35
export function getCurrentTime(): number;
@@ -13,3 +15,5 @@ export function setServiceData(serviceData: any): void;
1315
export function setStreamingThreshold(threshold: number): void;
1416

1517
export function getStreamingThreshold(): number;
18+
19+
export function getHttpResponseData(res: http.ServerResponse): object;

packages/core/lib/segments/segment_utils.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const { safeParseInt } = require('../utils');
12
var logger = require('../logger');
23

34
var DEFAULT_STREAMING_THRESHOLD = 100;
@@ -45,6 +46,27 @@ var utils = {
4546

4647
getStreamingThreshold: function getStreamingThreshold() {
4748
return utils.streamingThreshold;
49+
},
50+
51+
/**
52+
* Parses an HTTP response object to return an X-Ray compliant HTTP response object.
53+
* @param {http.ServerResponse} res
54+
* @returns {Object} - X-Ray response object to be added to (sub)segment
55+
*/
56+
getHttpResponseData: (res) => {
57+
const ret = {};
58+
if (!res) {
59+
return ret;
60+
}
61+
62+
const status = safeParseInt(res.statusCode);
63+
if (status !== 0) {
64+
ret.status = status;
65+
}
66+
if (res.headers && res.headers['content-length']) {
67+
ret.content_length = safeParseInt(res.headers['content-length']);
68+
}
69+
return ret;
4870
}
4971
};
5072

packages/core/lib/utils.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ export function objectWithoutProperties<T extends object, K extends keyof T>(
1919
keys: K[],
2020
preservePrototype?: boolean
2121
): Omit<T, K>;
22+
23+
export function safeParseInt(val: number | string): number;

packages/core/lib/utils.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,18 @@ var utils = {
240240
target[property] = obj[property];
241241
}
242242
return target;
243+
},
244+
245+
/**
246+
* Safely gets an integer from a string or number
247+
* @param {String | Number} - input to cast to integer
248+
* @returns {Number} - Integer representation of input, or 0 if input is not castable to int
249+
*/
250+
safeParseInt: (val) => {
251+
if (!val || isNaN(val)) {
252+
return 0;
253+
}
254+
return parseInt(val);
243255
}
244256
};
245257

packages/core/test/unit/segments/segment_utils.test.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,33 @@ describe('SegmentUtils', function() {
1414
assert.equal(SegmentUtils.streamingThreshold, 10);
1515
});
1616
});
17+
18+
describe('#getHttpResponseData', () => {
19+
it('should populate attributes as integers', () => {
20+
const responseWithStrings = {statusCode: '200', headers: {'content-length': '42'}};
21+
const res = SegmentUtils.getHttpResponseData(responseWithStrings);
22+
assert.deepEqual(res, {
23+
'content_length': 42,
24+
'status': 200
25+
});
26+
});
27+
28+
it('should omit missing properties', () => {
29+
const responseWithStatus = {statusCode: 200};
30+
const responseWithLength = {headers: {'content-length': 42}};
31+
const emptyResponse = {};
32+
33+
const statusRes = SegmentUtils.getHttpResponseData(responseWithStatus);
34+
const lengthRes = SegmentUtils.getHttpResponseData(responseWithLength);
35+
const emptyRes = SegmentUtils.getHttpResponseData(emptyResponse);
36+
37+
assert.deepEqual(statusRes, {
38+
'status': 200
39+
});
40+
assert.deepEqual(lengthRes, {
41+
'content_length': 42
42+
});
43+
assert.deepEqual(emptyRes, {});
44+
});
45+
});
1746
});

packages/core/test/unit/utils.test.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,4 +368,21 @@ describe('Utils', function() {
368368
assert.equal(Utils.wildcardMatch('?a?b*b?c?.?*.com', '1a2bjkdwfjkewb3c4.myelasticbeanstalkenv.org'), false);
369369
});
370370
});
371+
372+
describe('#safeParseInt', () => {
373+
it('should cast string to int', () => {
374+
assert.equal(Utils.safeParseInt('42'), 42);
375+
assert.equal(Utils.safeParseInt('15.0'), 15);
376+
});
377+
378+
it('should cast numbers to int', () => {
379+
assert.equal(Utils.safeParseInt(42), 42);
380+
assert.equal(Utils.safeParseInt(15.0), 15);
381+
});
382+
383+
it('should coerce NaN to zero', () => {
384+
assert.equal(Utils.safeParseInt('not a number'), 0);
385+
assert.equal(Utils.safeParseInt(NaN), 0);
386+
});
387+
});
371388
});

0 commit comments

Comments
 (0)