Skip to content

Commit 1da86e7

Browse files
shubhshethwilliazz
andauthored
fix: record resources with invalid names (#532)
* fix: Ignore URL construction error from invalid performance resource event * fix: Throw error when URL construction fails for invalid performance resource event * fix: Ignore error thrown from URL construction * test: add unit test * fix: record resources with invalid names * fix: Update unit test for invalid url * fix: Update hostname typo in isPutRumEventsCall tests --------- Co-authored-by: Billy <[email protected]>
1 parent 87e4cb4 commit 1da86e7

File tree

4 files changed

+78
-34
lines changed

4 files changed

+78
-34
lines changed

src/plugins/event-plugins/ResourcePlugin.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { InternalPlugin } from '../InternalPlugin';
2-
import { getResourceFileType, shuffle } from '../../utils/common-utils';
2+
import {
3+
getResourceFileType,
4+
isPutRumEventsCall,
5+
shuffle
6+
} from '../../utils/common-utils';
37
import { ResourceEvent } from '../../events/resource-event';
48
import { PERFORMANCE_RESOURCE_EVENT_TYPE } from '../utils/constant';
59
import {
@@ -88,12 +92,8 @@ export class ResourcePlugin extends InternalPlugin {
8892
duration,
8993
transferSize
9094
}: PerformanceResourceTiming): void => {
91-
const pathRegex =
92-
/.*\/application\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/events/;
93-
const entryUrl = new URL(name);
9495
if (
95-
entryUrl.host === this.context.config.endpointUrl.host &&
96-
pathRegex.test(entryUrl.pathname)
96+
isPutRumEventsCall(name, this.context.config.endpointUrl.hostname)
9797
) {
9898
// Ignore calls to PutRumEvents (i.e., the CloudWatch RUM data
9999
// plane), otherwise we end up in an infinite loop of recording

src/plugins/event-plugins/__tests__/ResourcePlugin.test.ts

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import {
22
resourceTiming,
33
putRumEventsDocument,
4-
putRumEventsGammaDocument,
5-
dataPlaneDocument,
64
imageResourceEventA,
75
imageResourceEventB,
86
navigationEvent,
@@ -95,32 +93,6 @@ describe('ResourcePlugin tests', () => {
9593
expect(record).not.toHaveBeenCalled();
9694
});
9795

98-
test('when resource is a PutRumEvents request with a path prefix then resource event is not recorded', async () => {
99-
// Setup
100-
doMockPerformanceObserver([putRumEventsGammaDocument]);
101-
102-
const plugin: ResourcePlugin = buildResourcePlugin();
103-
104-
// Run
105-
plugin.load(context);
106-
107-
// Assert
108-
expect(record).not.toHaveBeenCalled();
109-
});
110-
111-
test('when resource is not a PutRumEvents request but has the same host then the resource event is recorded', async () => {
112-
// Setup
113-
doMockPerformanceObserver([dataPlaneDocument]);
114-
115-
const plugin: ResourcePlugin = buildResourcePlugin();
116-
117-
// Run
118-
plugin.load(context);
119-
120-
// Assert
121-
expect(record).toHaveBeenCalled();
122-
});
123-
12496
test('when enabled then events are recorded', async () => {
12597
// Setup
12698
const plugin: ResourcePlugin = buildResourcePlugin();
@@ -235,4 +207,28 @@ describe('ResourcePlugin tests', () => {
235207

236208
expect(record).not.toHaveBeenCalled();
237209
});
210+
211+
test('when entry name is an invalid url then resource event is recorded', async () => {
212+
// setup
213+
const invalidEntry = {
214+
name: 'invalid.com',
215+
startTime: 0,
216+
duration: 10,
217+
entryType: 'resource'
218+
} as PerformanceEntry;
219+
doMockPerformanceObserver([invalidEntry]);
220+
221+
// run
222+
const plugin = buildResourcePlugin();
223+
plugin.load(context);
224+
225+
// assert
226+
expect(() => new URL(invalidEntry.name)).toThrowError();
227+
expect(() =>
228+
plugin.recordResourceEvent(
229+
invalidEntry as PerformanceResourceTiming
230+
)
231+
).not.toThrowError();
232+
expect(record).toHaveBeenCalled();
233+
});
238234
});

src/utils/__tests__/common-utils.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,33 @@ describe('Common utils tests', () => {
105105
utils.getResourceFileType(resourceUrl, utils.InitiatorType.CSS)
106106
).toEqual(utils.ResourceType.STYLESHEET);
107107
});
108+
109+
test('when url is has endpoint host and path then it is a PutRumEvents call', async () => {
110+
const endpointHost = 'dataplane.rum.us-west-2.amazonaws.com';
111+
const resourceUrl =
112+
'https://dataplane.rum.us-west-2.amazonaws.com/gamma/application/aa17a42c-e737-48f7-adaf-2e0905f48073/events';
113+
expect(utils.isPutRumEventsCall(resourceUrl, endpointHost)).toBe(true);
114+
});
115+
116+
test('when url has endpoint host but wrong path then it is not a PutRumEvents call', async () => {
117+
const endpointHost = 'dataplane.rum.us-west-2.amazonaws.com';
118+
const resourceUrl =
119+
'https://dataplane.rum.us-west-2.amazonaws.com/user';
120+
expect(utils.isPutRumEventsCall(resourceUrl, endpointHost)).toBe(false);
121+
});
122+
123+
test('when url has wrong host and wrong path then it is not a PutRumEvents call', async () => {
124+
const endpointHost = 'example.com';
125+
const resourceUrl =
126+
'https://dataplane.rum.us-west-2.amazonaws.com/user';
127+
expect(utils.isPutRumEventsCall(resourceUrl, endpointHost)).toBe(false);
128+
});
129+
130+
test('when url is invalid then it is not a PutRumEvents call', async () => {
131+
const endpointHost = 'dataplane.rum.us-west-2.amazonaws.com';
132+
const resourceUrl =
133+
'dataplane.rum.us-west-2.amazonaws.com/gamma/application/aa17a42c-e737-48f7-adaf-2e0905f48073/events';
134+
expect(() => new URL(endpointHost)).toThrowError();
135+
expect(utils.isPutRumEventsCall(resourceUrl, endpointHost)).toBe(false);
136+
});
108137
});

src/utils/common-utils.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,22 @@ export const isFCPSupported = () => {
222222
export const isLongTaskSupported = () => {
223223
return PerformanceObserver.supportedEntryTypes.includes('longtask');
224224
};
225+
226+
/** PutRumEvents regex pattern */
227+
const putRumEventsPattern =
228+
/.*\/application\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/events/;
229+
230+
export const isPutRumEventsCall = (
231+
url: string,
232+
endpointHost: string
233+
): boolean => {
234+
try {
235+
return (
236+
new URL(url).hostname === endpointHost &&
237+
putRumEventsPattern.test(url)
238+
);
239+
} catch (_) {
240+
// Ignore invalid URLs
241+
return false;
242+
}
243+
};

0 commit comments

Comments
 (0)