1818package org .openqa .selenium .remote ;
1919
2020import java .net .URI ;
21+ import java .util .ArrayList ;
22+ import java .util .List ;
2123import java .util .Map ;
2224import java .util .Optional ;
2325import java .util .concurrent .ConcurrentHashMap ;
2426import java .util .concurrent .atomic .AtomicLong ;
2527import java .util .function .Predicate ;
28+ import java .util .function .UnaryOperator ;
2629import org .openqa .selenium .Beta ;
2730import org .openqa .selenium .UsernameAndPassword ;
2831import org .openqa .selenium .WebDriver ;
2932import org .openqa .selenium .bidi .BiDi ;
3033import org .openqa .selenium .bidi .HasBiDi ;
3134import org .openqa .selenium .bidi .network .AddInterceptParameters ;
35+ import org .openqa .selenium .bidi .network .BytesValue ;
36+ import org .openqa .selenium .bidi .network .ContinueRequestParameters ;
37+ import org .openqa .selenium .bidi .network .Header ;
3238import org .openqa .selenium .bidi .network .InterceptPhase ;
39+ import org .openqa .selenium .bidi .network .RequestData ;
40+ import org .openqa .selenium .remote .http .Contents ;
41+ import org .openqa .selenium .remote .http .HttpMethod ;
42+ import org .openqa .selenium .remote .http .HttpRequest ;
3343
3444@ Beta
3545class RemoteNetwork implements Network {
@@ -39,13 +49,16 @@ class RemoteNetwork implements Network {
3949
4050 private final Map <Long , AuthDetails > authHandlers = new ConcurrentHashMap <>();
4151
52+ private final Map <Long , RequestDetails > requestHandlers = new ConcurrentHashMap <>();
53+
4254 private final AtomicLong callBackId = new AtomicLong (1 );
4355
4456 public RemoteNetwork (WebDriver driver ) {
4557 this .biDi = ((HasBiDi ) driver ).getBiDi ();
4658 this .network = new org .openqa .selenium .bidi .module .Network (driver );
4759
4860 interceptAuthTraffic ();
61+ interceptRequest ();
4962 }
5063
5164 private void interceptAuthTraffic () {
@@ -73,6 +86,68 @@ private Optional<UsernameAndPassword> getAuthCredentials(URI uri) {
7386 .findFirst ();
7487 }
7588
89+ private void interceptRequest () {
90+ this .network .addIntercept (new AddInterceptParameters (InterceptPhase .BEFORE_REQUEST_SENT ));
91+
92+ this .network .onBeforeRequestSent (
93+ beforeRequestSent -> {
94+ String requestId = beforeRequestSent .getRequest ().getRequestId ();
95+ URI uri = URI .create (beforeRequestSent .getRequest ().getUrl ());
96+
97+ ContinueRequestParameters continueRequestParameters =
98+ new ContinueRequestParameters (requestId );
99+
100+ Optional <UnaryOperator <HttpRequest >> requestHandler = getRequestHandler (uri );
101+
102+ if (requestHandler .isPresent ()) {
103+ RequestData interceptedRequest = beforeRequestSent .getRequest ();
104+ HttpRequest originalRequest =
105+ new HttpRequest (
106+ HttpMethod .getHttpMethod (interceptedRequest .getMethod ()),
107+ interceptedRequest .getUrl ());
108+
109+ interceptedRequest
110+ .getHeaders ()
111+ .forEach (
112+ header ->
113+ originalRequest .addHeader (header .getName (), header .getValue ().getValue ()));
114+
115+ HttpRequest modifiedRequest = requestHandler .get ().apply (originalRequest );
116+
117+ continueRequestParameters .method (modifiedRequest .getMethod ());
118+
119+ if (!uri .toString ().equals (modifiedRequest .getUri ())) {
120+ continueRequestParameters .url (modifiedRequest .getUri ());
121+ }
122+
123+ List <Header > headerList = new ArrayList <>();
124+ modifiedRequest .forEachHeader (
125+ (name , value ) ->
126+ headerList .add (
127+ new Header (name , new BytesValue (BytesValue .Type .STRING , value ))));
128+
129+ if (!headerList .isEmpty ()) {
130+ continueRequestParameters .headers (headerList );
131+ }
132+
133+ Contents .Supplier content = modifiedRequest .getContent ();
134+
135+ if (content .length () > 0 ) {
136+ continueRequestParameters .body (
137+ new BytesValue (BytesValue .Type .STRING , Contents .utf8String (content )));
138+ }
139+ }
140+ network .continueRequest (continueRequestParameters );
141+ });
142+ }
143+
144+ private Optional <UnaryOperator <HttpRequest >> getRequestHandler (URI uri ) {
145+ return requestHandlers .values ().stream ()
146+ .filter (requestDetails -> requestDetails .getFilter ().test (uri ))
147+ .map (RequestDetails ::getHandler )
148+ .findFirst ();
149+ }
150+
76151 @ Override
77152 public long addAuthenticationHandler (UsernameAndPassword usernameAndPassword ) {
78153 return addAuthenticationHandler (url -> true , usernameAndPassword );
@@ -97,6 +172,24 @@ public void clearAuthenticationHandlers() {
97172 authHandlers .clear ();
98173 }
99174
175+ @ Override
176+ public long addRequestHandler (Predicate <URI > filter , UnaryOperator <HttpRequest > handler ) {
177+ long id = this .callBackId .incrementAndGet ();
178+
179+ requestHandlers .put (id , new RequestDetails (filter , handler ));
180+ return id ;
181+ }
182+
183+ @ Override
184+ public void removeRequestHandler (long id ) {
185+ requestHandlers .remove (id );
186+ }
187+
188+ @ Override
189+ public void clearRequestHandlers () {
190+ requestHandlers .clear ();
191+ }
192+
100193 private class AuthDetails {
101194 private final Predicate <URI > filter ;
102195 private final UsernameAndPassword usernameAndPassword ;
@@ -114,4 +207,22 @@ public UsernameAndPassword getUsernameAndPassword() {
114207 return usernameAndPassword ;
115208 }
116209 }
210+
211+ private class RequestDetails {
212+ private final Predicate <URI > filter ;
213+ private final UnaryOperator <HttpRequest > handler ;
214+
215+ public RequestDetails (Predicate <URI > filter , UnaryOperator <HttpRequest > handler ) {
216+ this .filter = filter ;
217+ this .handler = handler ;
218+ }
219+
220+ public Predicate <URI > getFilter () {
221+ return this .filter ;
222+ }
223+
224+ public UnaryOperator <HttpRequest > getHandler () {
225+ return this .handler ;
226+ }
227+ }
117228}
0 commit comments