@@ -75,7 +75,42 @@ const generateUniqueMarkerID = () => {
7575} ;
7676
7777type OnBeforeSendHeadersOptions = `${chrome . webRequest . OnBeforeSendHeadersOptions } `;
78- type OnHeadersReceivedOptions = `${chrome . webRequest . OnHeadersReceivedOptions } `;
78+ type ReceiveHeaderOptions = `${chrome . webRequest . OnHeadersReceivedOptions } ` &
79+ `${chrome . webRequest . OnResponseStartedOptions } `;
80+
81+ // 删除关联与DNR: 不再处理 headerModifer 时清空 Map 关联 及 浏览器 Session Rule
82+ const headersSettled = ( markerID : string ) => {
83+ const dnrRule = headerModifierMap . get ( markerID ) ;
84+ const ruleID = dnrRule ?. rule . id ;
85+ if ( markerID ) {
86+ headerModifierMap . delete ( markerID ) ;
87+ }
88+ if ( ruleID ) {
89+ chrome . declarativeNetRequest . updateSessionRules (
90+ {
91+ removeRuleIds : [ ruleID ] ,
92+ } ,
93+ ( ) => {
94+ const lastError = chrome . runtime . lastError ;
95+ if ( lastError ) {
96+ console . error ( "chrome.declarativeNetRequest.updateSessionRules:" , lastError ) ;
97+ }
98+ removeSessionRuleIdEntry ( ruleID ) ;
99+ }
100+ ) ;
101+ }
102+ } ;
103+
104+ const cleanupOnAPIError = ( requestId : string ) => {
105+ const markerID = scXhrRequests . get ( requestId ) as string | undefined ;
106+ scXhrRequests . delete ( requestId ) ;
107+ if ( ! markerID ) return ;
108+ redirectedUrls . delete ( markerID ) ;
109+ nwErrorResults . delete ( markerID ) ;
110+ scXhrRequests . delete ( markerID ) ;
111+ headersReceivedMap . delete ( markerID ) ;
112+ headersSettled ( markerID ) ; // 处理完毕
113+ } ;
79114
80115// GMExternalDependencies接口定义
81116// 为了支持外部依赖注入,方便测试和扩展
@@ -851,7 +886,7 @@ export default class GMApi {
851886 if ( reqId ) scXhrRequests . delete ( reqId ) ;
852887 scXhrRequests . delete ( markerID ) ;
853888 headersReceivedMap . delete ( markerID ) ;
854- headerModifierMap . delete ( markerID ) ;
889+ headersSettled ( markerID ) ; // 处理完毕
855890 } ;
856891 let strategy : GMXhrStrategy | undefined = undefined ;
857892 if ( useFetch ) {
@@ -1410,6 +1445,7 @@ export default class GMApi {
14101445 if ( lastError ) {
14111446 console . error ( "chrome.runtime.lastError in chrome.webRequest.onBeforeRedirect:" , lastError ) ;
14121447 // webRequest API 出错不进行后续处理
1448+ cleanupOnAPIError ( details ?. requestId ) ;
14131449 return undefined ;
14141450 }
14151451 if ( details . tabId === - 1 ) {
@@ -1426,7 +1462,7 @@ export default class GMApi {
14261462 }
14271463 ) ;
14281464 const reqOpt : OnBeforeSendHeadersOptions [ ] = [ "requestHeaders" ] ;
1429- const respOpt : OnHeadersReceivedOptions [ ] = [ "responseHeaders" ] ;
1465+ const respOpt : ReceiveHeaderOptions [ ] = [ "responseHeaders" ] ;
14301466 if ( ! isFirefox ( ) ) {
14311467 reqOpt . push ( "extraHeaders" ) ;
14321468 respOpt . push ( "extraHeaders" ) ;
@@ -1438,14 +1474,16 @@ export default class GMApi {
14381474 if ( lastError ) {
14391475 console . error ( "chrome.runtime.lastError in chrome.webRequest.onErrorOccurred:" , lastError ) ;
14401476 // webRequest API 出错不进行后续处理
1477+ cleanupOnAPIError ( details ?. requestId ) ;
14411478 return undefined ;
14421479 }
14431480 if ( details . tabId === - 1 ) {
14441481 const markerID = scXhrRequests . get ( details . requestId ) ;
1445- if ( markerID ) {
1446- nwErrorResults . set ( markerID , details . error ) ;
1447- nwErrorResultPromises . get ( markerID ) ?.( ) ;
1448- }
1482+ if ( ! markerID ) return ;
1483+ nwErrorResults . set ( markerID , details . error ) ;
1484+ nwErrorResultPromises . get ( markerID ) ?.( ) ;
1485+
1486+ headersSettled ( markerID ) ; // 错误发生,不处理 header modifiers
14491487 }
14501488 } ,
14511489 {
@@ -1502,6 +1540,7 @@ export default class GMApi {
15021540 if ( lastError ) {
15031541 console . error ( "chrome.runtime.lastError in chrome.webRequest.onBeforeSendHeaders:" , lastError ) ;
15041542 // webRequest API 出错不进行后续处理
1543+ cleanupOnAPIError ( details ?. requestId ) ;
15051544 return undefined ;
15061545 }
15071546 if ( details . tabId === - 1 ) {
@@ -1510,7 +1549,11 @@ export default class GMApi {
15101549 if ( requestHeaders ) {
15111550 // 如 onBeforeSendHeaders 是在 modifyHeaders 前执行,可以更新一下 reqId 和 markerID 的关联
15121551 const markerID = requestHeaders ?. find ( ( h ) => h . name . toLowerCase ( ) === "x-sc-request-marker" ) ?. value ;
1513- if ( markerID ) scXhrRequests . set ( reqId , markerID ) ;
1552+ if ( markerID ) {
1553+ // 双向关联
1554+ scXhrRequests . set ( reqId , markerID ) ;
1555+ scXhrRequests . set ( markerID , reqId ) ; // 用于清理
1556+ }
15141557 }
15151558 const markerID = scXhrRequests . get ( reqId ) ;
15161559 if ( ! markerID ) return undefined ;
@@ -1525,12 +1568,14 @@ export default class GMApi {
15251568 } ,
15261569 reqOpt
15271570 ) ;
1571+
15281572 chrome . webRequest . onHeadersReceived . addListener (
15291573 ( details ) => {
15301574 const lastError = chrome . runtime . lastError ;
15311575 if ( lastError ) {
15321576 console . error ( "chrome.runtime.lastError in chrome.webRequest.onBeforeSendHeaders:" , lastError ) ;
15331577 // webRequest API 出错不进行后续处理
1578+ cleanupOnAPIError ( details ?. requestId ) ;
15341579 return undefined ;
15351580 }
15361581 if ( details . tabId === - 1 ) {
@@ -1597,21 +1642,7 @@ export default class GMApi {
15971642 }
15981643 }
15991644 ) ;
1600- } else {
1601- // 删除关联与DNR
1602- headerModifierMap . delete ( markerID ) ;
1603- chrome . declarativeNetRequest . updateSessionRules (
1604- {
1605- removeRuleIds : [ rule . id ] ,
1606- } ,
1607- ( ) => {
1608- const lastError = chrome . runtime . lastError ;
1609- if ( lastError ) {
1610- console . error ( "chrome.declarativeNetRequest.updateSessionRules:" , lastError ) ;
1611- }
1612- removeSessionRuleIdEntry ( rule . id ) ;
1613- }
1614- ) ;
1645+ return ;
16151646 }
16161647 }
16171648 }
@@ -1624,6 +1655,38 @@ export default class GMApi {
16241655 respOpt
16251656 ) ;
16261657
1658+ chrome . webRequest . onResponseStarted . addListener (
1659+ ( details ) => {
1660+ // onResponseStarted 触发后,headers 不会再有改动
1661+ const lastError = chrome . runtime . lastError ;
1662+ if ( lastError ) {
1663+ console . error ( "chrome.runtime.lastError in chrome.webRequest.onResponseStarted:" , lastError ) ;
1664+ // webRequest API 出错不进行后续处理
1665+ cleanupOnAPIError ( details ?. requestId ) ;
1666+ return undefined ;
1667+ }
1668+ if ( details . tabId === - 1 ) {
1669+ const reqId = details . requestId ;
1670+
1671+ const markerID = scXhrRequests . get ( reqId ) ;
1672+ if ( ! markerID ) return ;
1673+ if ( details . responseHeaders && details . statusCode ) {
1674+ headersReceivedMap . set ( markerID , {
1675+ responseHeaders : details . responseHeaders ,
1676+ statusCode : details . statusCode ,
1677+ } ) ;
1678+ }
1679+
1680+ headersSettled ( markerID ) ; // onResponseStarted 已触发,headers 已固定
1681+ }
1682+ } ,
1683+ {
1684+ urls : [ "<all_urls>" ] ,
1685+ types : [ "xmlhttprequest" ] ,
1686+ } ,
1687+ respOpt
1688+ ) ;
1689+
16271690 const ruleId = 999 ;
16281691 const rule = {
16291692 id : ruleId ,
0 commit comments