@@ -866,17 +866,29 @@ export class Recorder extends EventEmitter {
866866 }
867867
868868 addExternalFetch ( url : string , cdp : CDPSession ) {
869- logger . debug (
870- "Handling fetch from behavior" ,
871- { url, ...this . logDetails } ,
872- "recorder" ,
873- ) ;
874869 const reqresp = new RequestResponseInfo ( "0" ) ;
875870 reqresp . url = url ;
876871 reqresp . method = "GET" ;
877872 reqresp . frameId = this . mainFrameId || undefined ;
878- this . addAsyncFetch ( { reqresp, recorder : this , cdp } ) ;
879- // return true if successful
873+
874+ const details = { url, ...this . logDetails } ;
875+
876+ const fetchIfNotDupe = async ( ) => {
877+ if ( await this . isDupeFetch ( reqresp ) ) {
878+ logger . debug ( "Skipping dupe fetch from behavior" , details , "recorder" ) ;
879+ return false ;
880+ }
881+
882+ logger . debug ( "Handling fetch from behavior" , details , "recorder" ) ;
883+
884+ this . addAsyncFetch ( { reqresp, recorder : this , cdp } ) ;
885+ } ;
886+
887+ void fetchIfNotDupe ( ) . catch ( ( ) =>
888+ logger . warn ( "Error fetching URL from behavior" , details , "recorder" ) ,
889+ ) ;
890+
891+ // return true to indicate no need for in-browser fetch
880892 return true ;
881893 }
882894
@@ -1451,6 +1463,16 @@ export class Recorder extends EventEmitter {
14511463 "recorder" ,
14521464 ) ;
14531465 reqresp . truncated = "disconnect" ;
1466+ } finally {
1467+ try {
1468+ await cdp . send ( "IO.close" , { handle : stream } ) ;
1469+ } catch ( e ) {
1470+ logger . warn (
1471+ "takeStream close failed" ,
1472+ { url : reqresp . url , ...this . logDetails } ,
1473+ "recorder" ,
1474+ ) ;
1475+ }
14541476 }
14551477 }
14561478
@@ -1662,6 +1684,7 @@ class AsyncFetcher {
16621684
16631685 stream ?: string ;
16641686 resp ?: Response ;
1687+ abort ?: AbortController ;
16651688
16661689 maxFetchSize : number ;
16671690
@@ -1753,7 +1776,11 @@ class AsyncFetcher {
17531776 throw new Error ( "resp body missing" ) ;
17541777 }
17551778
1756- return await recorder . serializeToWARC ( reqresp , iter ) ;
1779+ if ( ! ( await recorder . serializeToWARC ( reqresp , iter ) ) ) {
1780+ await this . doCancel ( ) ;
1781+ return false ;
1782+ }
1783+ return true ;
17571784 } catch ( e ) {
17581785 logger . warn (
17591786 "Async load body failed" ,
@@ -1765,14 +1792,10 @@ class AsyncFetcher {
17651792 }
17661793
17671794 async doCancel ( ) {
1768- const { resp, useBrowserNetwork } = this ;
1769- if ( ! useBrowserNetwork && resp ) {
1770- if ( resp . status >= 300 && resp . status < 400 ) {
1771- await resp . arrayBuffer ( ) ;
1772- } else {
1773- // otherwise, just cancel
1774- resp . body ?. cancel ( ) . catch ( ( ) => { } ) ;
1775- }
1795+ const { abort } = this ;
1796+ if ( abort ) {
1797+ abort . abort ( ) ;
1798+ this . abort = undefined ;
17761799 }
17771800 }
17781801
@@ -1796,12 +1819,15 @@ class AsyncFetcher {
17961819 } ) ;
17971820 }
17981821
1822+ this . abort = new AbortController ( ) ;
1823+
17991824 const resp = await fetch ( url ! , {
18001825 method,
18011826 headers,
18021827 body : reqresp . postData || undefined ,
18031828 redirect : this . manualRedirect ? "manual" : "follow" ,
18041829 dispatcher,
1830+ signal : this . abort . signal ,
18051831 } ) ;
18061832
18071833 if (
0 commit comments