Skip to content

Commit cae71f7

Browse files
committed
content-type body filtering
1 parent 8c41efd commit cae71f7

File tree

1 file changed

+86
-49
lines changed
  • packages/rrweb/src/plugins/network/record

1 file changed

+86
-49
lines changed

packages/rrweb/src/plugins/network/record/index.ts

Lines changed: 86 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ type NetworkRecordOptions = {
2929
initiatorTypes?: InitiatorType[];
3030
ignoreRequestFn?: (data: NetworkRequest) => boolean;
3131
recordHeaders?: boolean | { request: boolean; response: boolean };
32-
recordBody?: boolean | { request: boolean; response: boolean };
32+
recordBody?:
33+
| boolean
34+
| string[]
35+
| { request: boolean | string[]; response: boolean | string[] };
3336
recordInitialRequests?: boolean;
3437
};
3538

@@ -155,6 +158,13 @@ function initPerformanceObserver(
155158
};
156159
}
157160

161+
function getContentType(headers: Headers) {
162+
const contentTypeHeader = Object.keys(headers).find(
163+
(key) => key.toLowerCase() === 'content-type',
164+
);
165+
return contentTypeHeader && headers[contentTypeHeader];
166+
}
167+
158168
async function getRequestPerformanceEntry(
159169
win: IWindow,
160170
initiatorType: string,
@@ -238,21 +248,28 @@ function initXhrObserver(
238248
const networkRequest: Partial<NetworkRequest> = {};
239249
let after: number | undefined;
240250
let before: number | undefined;
251+
const requestHeaders: Headers = {};
252+
const originalSetRequestHeader = xhr.setRequestHeader.bind(xhr);
253+
xhr.setRequestHeader = (header: string, value: string) => {
254+
requestHeaders[header] = value;
255+
return originalSetRequestHeader(header, value);
256+
};
241257
if (recordRequestHeaders) {
242-
networkRequest.requestHeaders = {};
243-
const originalSetRequestHeader = xhr.setRequestHeader.bind(xhr);
244-
xhr.setRequestHeader = (header: string, value: string) => {
245-
networkRequest.requestHeaders![header] = value;
246-
return originalSetRequestHeader(header, value);
247-
};
258+
networkRequest.requestHeaders = requestHeaders;
248259
}
249260
const originalSend = xhr.send.bind(xhr);
250261
xhr.send = (body) => {
251262
if (recordRequestBody) {
252-
if (body === undefined || body === null) {
253-
networkRequest.requestBody = null;
254-
} else {
255-
networkRequest.requestBody = body;
263+
const contentType = getContentType(requestHeaders);
264+
if (
265+
recordRequestBody === true ||
266+
(contentType && recordRequestBody.includes(contentType))
267+
) {
268+
if (body === undefined || body === null) {
269+
networkRequest.requestBody = null;
270+
} else {
271+
networkRequest.requestBody = body;
272+
}
256273
}
257274
}
258275
after = win.performance.now();
@@ -263,24 +280,31 @@ function initXhrObserver(
263280
return;
264281
}
265282
before = win.performance.now();
283+
const responseHeaders: Headers = {};
284+
const rawHeaders = xhr.getAllResponseHeaders();
285+
const headers = rawHeaders.trim().split(/[\r\n]+/);
286+
headers.forEach((line) => {
287+
const parts = line.split(': ');
288+
const header = parts.shift();
289+
const value = parts.join(': ');
290+
if (header) {
291+
responseHeaders[header] = value;
292+
}
293+
});
266294
if (recordResponseHeaders) {
267-
networkRequest.responseHeaders = {};
268-
const rawHeaders = xhr.getAllResponseHeaders();
269-
const headers = rawHeaders.trim().split(/[\r\n]+/);
270-
headers.forEach((line) => {
271-
const parts = line.split(': ');
272-
const header = parts.shift();
273-
const value = parts.join(': ');
274-
if (header) {
275-
networkRequest.responseHeaders![header] = value;
276-
}
277-
});
295+
networkRequest.responseHeaders = responseHeaders;
278296
}
279297
if (recordResponseBody) {
280-
if (xhr.response === undefined || xhr.response === null) {
281-
networkRequest.responseBody = null;
282-
} else {
283-
networkRequest.responseBody = xhr.response;
298+
const contentType = getContentType(responseHeaders);
299+
if (
300+
recordResponseBody === true ||
301+
(contentType && recordResponseBody.includes(contentType))
302+
) {
303+
if (xhr.response === undefined || xhr.response === null) {
304+
networkRequest.responseBody = null;
305+
} else {
306+
networkRequest.responseBody = xhr.response;
307+
}
284308
}
285309
}
286310
getRequestPerformanceEntry(
@@ -360,39 +384,53 @@ function initFetchObserver(
360384
let after: number | undefined;
361385
let before: number | undefined;
362386
try {
387+
const requestHeaders: Headers = {};
388+
req.headers.forEach((value, header) => {
389+
requestHeaders[header] = value;
390+
});
363391
if (recordRequestHeaders) {
364-
networkRequest.requestHeaders = {};
365-
req.headers.forEach((value, header) => {
366-
networkRequest.requestHeaders![header] = value;
367-
});
392+
networkRequest.requestHeaders = requestHeaders;
368393
}
369394
if (recordRequestBody) {
370-
if (req.body === undefined || req.body === null) {
371-
networkRequest.requestBody = null;
372-
} else {
373-
networkRequest.requestBody = req.body;
395+
const contentType = getContentType(requestHeaders);
396+
if (
397+
recordRequestBody === true ||
398+
(contentType && recordRequestBody.includes(contentType))
399+
) {
400+
if (req.body === undefined || req.body === null) {
401+
networkRequest.requestBody = null;
402+
} else {
403+
networkRequest.requestBody = req.body;
404+
}
374405
}
375406
}
376407
after = win.performance.now();
377408
res = await originalFetch(req);
378409
before = win.performance.now();
410+
const responseHeaders: Headers = {};
411+
res.headers.forEach((value, header) => {
412+
responseHeaders[header] = value;
413+
});
379414
if (recordResponseHeaders) {
380-
networkRequest.responseHeaders = {};
381-
res.headers.forEach((value, header) => {
382-
networkRequest.responseHeaders![header] = value;
383-
});
415+
networkRequest.responseHeaders = responseHeaders;
384416
}
385417
if (recordResponseBody) {
386-
let body: string | undefined;
387-
try {
388-
body = await res.clone().text();
389-
} catch {
390-
//
391-
}
392-
if (res.body === undefined || res.body === null) {
393-
networkRequest.responseBody = null;
394-
} else {
395-
networkRequest.responseBody = body;
418+
const contentType = getContentType(responseHeaders);
419+
if (
420+
recordResponseBody === true ||
421+
(contentType && recordResponseBody.includes(contentType))
422+
) {
423+
let body: string | undefined;
424+
try {
425+
body = await res.clone().text();
426+
} catch {
427+
//
428+
}
429+
if (res.body === undefined || res.body === null) {
430+
networkRequest.responseBody = null;
431+
} else {
432+
networkRequest.responseBody = body;
433+
}
396434
}
397435
}
398436
return res;
@@ -419,7 +457,6 @@ function initFetchObserver(
419457
}
420458
};
421459
});
422-
423460
return () => {
424461
restorePatch();
425462
};

0 commit comments

Comments
 (0)