1818const  {  Network : getNetwork  }  =  require ( '../bidi/network' ) 
1919const  {  InterceptPhase }  =  require ( '../bidi/interceptPhase' ) 
2020const  {  AddInterceptParameters }  =  require ( '../bidi/addInterceptParameters' ) 
21+ const  {  ContinueRequestParameters }  =  require ( '../bidi/continueRequestParameters' ) 
22+ const  {  ProvideResponseParameters }  =  require ( '../bidi/provideResponseParameters' ) 
23+ const  {  Request }  =  require ( './http' ) 
24+ const  {  BytesValue,  Header }  =  require ( '../bidi/networkTypes' ) 
2125
2226class  Network  { 
2327  #callbackId =  0 
2428  #driver
2529  #network
2630  #authHandlers =  new  Map ( ) 
31+   #requestHandlers =  new  Map ( ) 
32+   #responseHandlers =  new  Map ( ) 
2733
2834  constructor ( driver )  { 
2935    this . #driver =  driver 
@@ -43,6 +49,8 @@ class Network {
4349
4450    await  this . #network. addIntercept ( new  AddInterceptParameters ( InterceptPhase . AUTH_REQUIRED ) ) 
4551
52+     await  this . #network. addIntercept ( new  AddInterceptParameters ( InterceptPhase . BEFORE_REQUEST_SENT ) ) 
53+ 
4654    await  this . #network. authRequired ( async  ( event )  =>  { 
4755      const  requestId  =  event . request . request 
4856      const  uri  =  event . request . url 
@@ -54,6 +62,76 @@ class Network {
5462
5563      await  this . #network. continueWithAuthNoCredentials ( requestId ) 
5664    } ) 
65+ 
66+     await  this . #network. beforeRequestSent ( async  ( event )  =>  { 
67+       const  requestId  =  event . request . request 
68+       const  requestData  =  event . request 
69+ 
70+       // Build the original request from the intercepted request details. 
71+       const  originalRequest  =  new  Request ( requestData . method ,  requestData . url ,  null ,  new  Map ( requestData . headers ) ) 
72+ 
73+       let  requestHandler  =  this . getRequestHandler ( originalRequest ) 
74+       let  responseHandler  =  this . getResponseHandler ( originalRequest ) 
75+ 
76+       // Populate the headers of the original request. 
77+       // Body is not available as part of WebDriver Spec, hence we cannot add that or use that. 
78+ 
79+       const  continueRequestParams  =  new  ContinueRequestParameters ( requestId ) 
80+ 
81+       // If a response handler exists, we mock the response instead of modifying the outgoing request 
82+       if  ( responseHandler  !==  null )  { 
83+         const  modifiedResponse  =  await  responseHandler ( ) 
84+ 
85+         const  provideResponseParams  =  new  ProvideResponseParameters ( requestId ) 
86+         provideResponseParams . statusCode ( modifiedResponse . status ) 
87+ 
88+         // Convert headers 
89+         if  ( modifiedResponse . headers . size  >  0 )  { 
90+           const  headers  =  [ ] 
91+ 
92+           modifiedResponse . headers . forEach ( ( value ,  key )  =>  { 
93+             headers . push ( new  Header ( key ,  new  BytesValue ( 'string' ,  value ) ) ) 
94+           } ) 
95+           provideResponseParams . headers ( headers ) 
96+         } 
97+ 
98+         // Convert body if available 
99+         if  ( modifiedResponse . body  &&  modifiedResponse . body . length  >  0 )  { 
100+           provideResponseParams . body ( new  BytesValue ( 'string' ,  modifiedResponse . body ) ) 
101+         } 
102+ 
103+         await  this . #network. provideResponse ( provideResponseParams ) 
104+         return 
105+       } 
106+ 
107+       // If request handler exists, modify the request 
108+       if  ( requestHandler  !==  null )  { 
109+         const  modifiedRequest  =  requestHandler ( originalRequest ) 
110+ 
111+         continueRequestParams . method ( modifiedRequest . method ) 
112+ 
113+         if  ( originalRequest . path  !==  modifiedRequest . path )  { 
114+           continueRequestParams . url ( modifiedRequest . path ) 
115+         } 
116+ 
117+         // Convert headers 
118+         if  ( modifiedRequest . headers . size  >  0 )  { 
119+           const  headers  =  [ ] 
120+ 
121+           modifiedRequest . headers . forEach ( ( value ,  key )  =>  { 
122+             headers . push ( new  Header ( key ,  new  BytesValue ( 'string' ,  value ) ) ) 
123+           } ) 
124+           continueRequestParams . headers ( headers ) 
125+         } 
126+ 
127+         if  ( modifiedRequest . data  &&  modifiedRequest . data . length  >  0 )  { 
128+           continueRequestParams . body ( new  BytesValue ( 'string' ,  modifiedRequest . data ) ) 
129+         } 
130+       } 
131+ 
132+       // Continue with the modified or original request 
133+       await  this . #network. continueRequest ( continueRequestParams ) 
134+     } ) 
57135  } 
58136
59137  getAuthCredentials ( uri )  { 
@@ -64,6 +142,27 @@ class Network {
64142    } 
65143    return  null 
66144  } 
145+ 
146+   getRequestHandler ( req )  { 
147+     for  ( let  [ ,  value ]  of  this . #requestHandlers)  { 
148+       const  filter  =  value . filter 
149+       if  ( filter ( req ) )  { 
150+         return  value . handler 
151+       } 
152+     } 
153+     return  null 
154+   } 
155+ 
156+   getResponseHandler ( req )  { 
157+     for  ( let  [ ,  value ]  of  this . #responseHandlers)  { 
158+       const  filter  =  value . filter 
159+       if  ( filter ( req ) )  { 
160+         return  value . handler 
161+       } 
162+     } 
163+     return  null 
164+   } 
165+ 
67166  async  addAuthenticationHandler ( username ,  password ,  uri  =  '//' )  { 
68167    await  this . #init( ) 
69168
@@ -86,6 +185,82 @@ class Network {
86185  async  clearAuthenticationHandlers ( )  { 
87186    this . #authHandlers. clear ( ) 
88187  } 
188+ 
189+   /** 
190+    * Adds a request handler that filters requests based on a predicate function. 
191+    * @param  {Function } filter - A function that takes an HTTP request and returns true or false. 
192+    * @param  {Function } handler - A function that takes an HTTP request and returns a modified request. 
193+    * @returns  {number } - A unique handler ID. 
194+    * @throws  {Error } - If filter is not a function or handler does not return a request. 
195+    */ 
196+   async  addRequestHandler ( filter ,  handler )  { 
197+     if  ( typeof  filter  !==  'function' )  { 
198+       throw  new  Error ( 'Filter must be a function.' ) 
199+     } 
200+ 
201+     if  ( typeof  handler  !==  'function' )  { 
202+       throw  new  Error ( 'Handler must be a function.' ) 
203+     } 
204+ 
205+     await  this . #init( ) 
206+ 
207+     const  id  =  this . #callbackId++ 
208+ 
209+     this . #requestHandlers. set ( id ,  {  filter,  handler } ) 
210+     return  id 
211+   } 
212+ 
213+   async  removeRequestHandler ( id )  { 
214+     await  this . #init( ) 
215+ 
216+     if  ( this . #requestHandlers. has ( id ) )  { 
217+       this . #requestHandlers. delete ( id ) 
218+     }  else  { 
219+       throw  Error ( `Callback with id ${ id }   not found` ) 
220+     } 
221+   } 
222+ 
223+   async  clearRequestHandlers ( )  { 
224+     this . #requestHandlers. clear ( ) 
225+   } 
226+ 
227+   /** 
228+    * Adds a response handler that mocks responses. 
229+    * @param  {Function } filter - A function that takes an HTTP request, returning a boolean. 
230+    * @param  {Function } handler - A function that returns a mocked HTTP response. 
231+    * @returns  {number } - A unique handler ID. 
232+    * @throws  {Error } - If filter is not a function or handler is not an async function. 
233+    */ 
234+   async  addResponseHandler ( filter ,  handler )  { 
235+     if  ( typeof  filter  !==  'function' )  { 
236+       throw  new  Error ( 'Filter must be a function.' ) 
237+     } 
238+ 
239+     if  ( typeof  handler  !==  'function' )  { 
240+       throw  new  Error ( 'Handler must be a function.' ) 
241+     } 
242+ 
243+     await  this . #init( ) 
244+ 
245+     const  id  =  this . #callbackId++ 
246+ 
247+     this . #responseHandlers. set ( id ,  {  filter,  handler } ) 
248+     return  id 
249+   } 
250+ 
251+   async  removeResponseHandler ( id )  { 
252+     await  this . #init( ) 
253+ 
254+     if  ( this . #responseHandlers. has ( id ) )  { 
255+       this . #responseHandlers. delete ( id ) 
256+     }  else  { 
257+       throw  Error ( `Callback with id ${ id }   not found` ) 
258+     } 
259+   } 
260+ 
261+   async  clearResponseHandlers ( )  { 
262+     this . #responseHandlers. clear ( ) 
263+   } 
89264} 
90265
91266module . exports  =  Network 
0 commit comments