|
1 | 1 | import type { listenerHandler, RecordPlugin, IWindow } from '@rrweb/types'; |
2 | 2 | import { patch } from '@rrweb/utils'; |
3 | 3 |
|
4 | | -function findLast<T>( |
5 | | - array: Array<T>, |
6 | | - predicate: (value: T) => boolean, |
7 | | -): T | undefined { |
8 | | - const length = array.length; |
9 | | - for (let i = length - 1; i >= 0; i -= 1) { |
10 | | - if (predicate(array[i])) { |
11 | | - return array[i]; |
12 | | - } |
13 | | - } |
14 | | -} |
15 | | - |
16 | 4 | export type InitiatorType = |
17 | 5 | | 'audio' |
18 | 6 | | 'beacon' |
@@ -89,12 +77,17 @@ type Body = |
89 | 77 | | ReadableStream<Uint8Array> |
90 | 78 | | null; |
91 | 79 |
|
92 | | -type NetworkRequest = Omit<PerformanceEntry, 'toJSON'> & { |
| 80 | +type NetworkRequest = Omit< |
| 81 | + PerformanceEntry, |
| 82 | + 'toJSON' | 'startTime' | 'endTime' | 'duration' | 'entryType' |
| 83 | +> & { |
93 | 84 | method?: string; |
94 | 85 | initiatorType?: InitiatorType; |
95 | 86 | status?: number; |
96 | 87 | startTime?: number; |
97 | 88 | endTime?: number; |
| 89 | + duration?: number; |
| 90 | + entryType?: string; |
98 | 91 | requestHeaders?: Headers; |
99 | 92 | requestBody?: Body; |
100 | 93 | responseHeaders?: Headers; |
@@ -345,22 +338,23 @@ function initXhrObserver( |
345 | 338 | before, |
346 | 339 | ) |
347 | 340 | .then((entry) => { |
348 | | - if (!entry) return; |
349 | | - const request: NetworkRequest = { |
350 | | - method: req.method, |
351 | | - initiatorType: entry.initiatorType as InitiatorType, |
352 | | - duration: entry.duration, |
353 | | - entryType: entry.entryType, |
354 | | - name: entry.name, |
355 | | - status: xhr.status, |
356 | | - startTime: Math.round(entry.startTime), |
357 | | - endTime: Math.round(entry.responseEnd), |
358 | | - requestHeaders: networkRequest.requestHeaders, |
359 | | - requestBody: networkRequest.requestBody, |
360 | | - responseHeaders: networkRequest.responseHeaders, |
361 | | - responseBody: networkRequest.responseBody, |
362 | | - }; |
363 | | - cb({ requests: [request] }); |
| 341 | + if (!entry) { |
| 342 | + // https://github.com/rrweb-io/rrweb/pull/1105#issuecomment-1953808336 |
| 343 | + const requests = prepareRequestWithoutPerformance( |
| 344 | + req, |
| 345 | + networkRequest, |
| 346 | + ); |
| 347 | + cb({ requests }); |
| 348 | + return; |
| 349 | + } |
| 350 | + |
| 351 | + const requests = prepareRequest( |
| 352 | + entry, |
| 353 | + req.method, |
| 354 | + xhr.status, |
| 355 | + networkRequest, |
| 356 | + ); |
| 357 | + cb({ requests }); |
364 | 358 | }) |
365 | 359 | .catch(() => { |
366 | 360 | // |
@@ -446,22 +440,23 @@ function initFetchObserver( |
446 | 440 | } finally { |
447 | 441 | getRequestPerformanceEntry(win, 'fetch', req.url, after, before) |
448 | 442 | .then((entry) => { |
449 | | - if (!entry) return; |
450 | | - const request: NetworkRequest = { |
451 | | - method: req.method, |
452 | | - initiatorType: entry.initiatorType as InitiatorType, |
453 | | - duration: entry.duration, |
454 | | - entryType: entry.entryType, |
455 | | - name: entry.name, |
456 | | - status: res?.status, |
457 | | - startTime: Math.round(entry.startTime), |
458 | | - endTime: Math.round(entry.responseEnd), |
459 | | - requestHeaders: networkRequest.requestHeaders, |
460 | | - requestBody: networkRequest.requestBody, |
461 | | - responseHeaders: networkRequest.responseHeaders, |
462 | | - responseBody: networkRequest.responseBody, |
463 | | - }; |
464 | | - cb({ requests: [request] }); |
| 443 | + if (!entry) { |
| 444 | + // https://github.com/rrweb-io/rrweb/pull/1105#issuecomment-1953808336 |
| 445 | + const requests = prepareRequestWithoutPerformance( |
| 446 | + req, |
| 447 | + networkRequest, |
| 448 | + ); |
| 449 | + cb({ requests }); |
| 450 | + return; |
| 451 | + } |
| 452 | + |
| 453 | + const requests = prepareRequest( |
| 454 | + entry, |
| 455 | + req.method, |
| 456 | + res?.status, |
| 457 | + networkRequest, |
| 458 | + ); |
| 459 | + cb({ requests }); |
465 | 460 | }) |
466 | 461 | .catch(() => { |
467 | 462 | // |
@@ -509,6 +504,58 @@ function initNetworkObserver( |
509 | 504 | }; |
510 | 505 | } |
511 | 506 |
|
| 507 | +function prepareRequest( |
| 508 | + entry: PerformanceResourceTiming, |
| 509 | + method: string | undefined, |
| 510 | + status: number | undefined, |
| 511 | + networkRequest: Partial<NetworkRequest>, |
| 512 | +): NetworkRequest[] { |
| 513 | + const request: NetworkRequest = { |
| 514 | + method, |
| 515 | + initiatorType: entry.initiatorType as InitiatorType, |
| 516 | + duration: entry.duration, |
| 517 | + entryType: entry.entryType, |
| 518 | + name: entry.name, |
| 519 | + status, |
| 520 | + startTime: Math.round(entry.startTime), |
| 521 | + endTime: Math.round(entry.responseEnd), |
| 522 | + requestHeaders: networkRequest.requestHeaders, |
| 523 | + requestBody: networkRequest.requestBody, |
| 524 | + responseHeaders: networkRequest.responseHeaders, |
| 525 | + responseBody: networkRequest.responseBody, |
| 526 | + }; |
| 527 | + |
| 528 | + return [request]; |
| 529 | +} |
| 530 | + |
| 531 | +function prepareRequestWithoutPerformance( |
| 532 | + req: Request, |
| 533 | + networkRequest: Partial<NetworkRequest>, |
| 534 | +): NetworkRequest[] { |
| 535 | + const request: NetworkRequest = { |
| 536 | + name: req.url, |
| 537 | + method: req.method, |
| 538 | + requestHeaders: networkRequest.requestHeaders, |
| 539 | + requestBody: networkRequest.requestBody, |
| 540 | + responseHeaders: networkRequest.responseHeaders, |
| 541 | + responseBody: networkRequest.responseBody, |
| 542 | + }; |
| 543 | + |
| 544 | + return [request]; |
| 545 | +} |
| 546 | + |
| 547 | +function findLast<T>( |
| 548 | + array: Array<T>, |
| 549 | + predicate: (value: T) => boolean, |
| 550 | +): T | undefined { |
| 551 | + const length = array.length; |
| 552 | + for (let i = length - 1; i >= 0; i -= 1) { |
| 553 | + if (predicate(array[i])) { |
| 554 | + return array[i]; |
| 555 | + } |
| 556 | + } |
| 557 | +} |
| 558 | + |
512 | 559 | export const PLUGIN_NAME = 'rrweb/network@1'; |
513 | 560 |
|
514 | 561 | export const getRecordNetworkPlugin: ( |
|
0 commit comments