Skip to content

Commit 1b941bd

Browse files
committed
[bidi][java] Add network request handler APIs
1 parent ef1b422 commit 1b941bd

File tree

7 files changed

+409
-10
lines changed

7 files changed

+409
-10
lines changed

java/src/org/openqa/selenium/bidi/network/Header.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class Header {
2525
private final String name;
2626
private final BytesValue value;
2727

28-
private Header(String name, BytesValue value) {
28+
public Header(String name, BytesValue value) {
2929
this.name = name;
3030
this.value = value;
3131
}

java/src/org/openqa/selenium/bidi/network/ResponseData.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public class ResponseData {
2828
private final String url;
2929

3030
private final String protocol;
31-
private final long status;
31+
private final int status;
3232
private final String statusText;
3333
private final boolean fromCache;
3434
private final List<Header> headers;
@@ -42,7 +42,7 @@ public class ResponseData {
4242
private ResponseData(
4343
String url,
4444
String protocol,
45-
long status,
45+
int status,
4646
String statusText,
4747
boolean fromCache,
4848
List<Header> headers,
@@ -69,7 +69,7 @@ private ResponseData(
6969
public static ResponseData fromJson(JsonInput input) {
7070
String url = null;
7171
String protocol = null;
72-
long status = 0;
72+
int status = 0;
7373
String statusText = null;
7474
boolean fromCache = false;
7575
List<Header> headers = new ArrayList<>();
@@ -89,7 +89,7 @@ public static ResponseData fromJson(JsonInput input) {
8989
protocol = input.read(String.class);
9090
break;
9191
case "status":
92-
status = input.read(Long.class);
92+
status = input.read(Integer.class);
9393
break;
9494
case "statusText":
9595
statusText = input.read(String.class);
@@ -150,7 +150,7 @@ public String getProtocol() {
150150
return protocol;
151151
}
152152

153-
public long getStatus() {
153+
public int getStatus() {
154154
return status;
155155
}
156156

java/src/org/openqa/selenium/remote/Network.java

+8
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919

2020
import java.net.URI;
2121
import java.util.function.Predicate;
22+
import java.util.function.UnaryOperator;
2223
import org.openqa.selenium.Beta;
2324
import org.openqa.selenium.UsernameAndPassword;
25+
import org.openqa.selenium.remote.http.HttpRequest;
2426

2527
@Beta
2628
public interface Network {
@@ -32,4 +34,10 @@ public interface Network {
3234
void removeAuthenticationHandler(long id);
3335

3436
void clearAuthenticationHandlers();
37+
38+
long addRequestHandler(Predicate<URI> filter, UnaryOperator<HttpRequest> handler);
39+
40+
void removeRequestHandler(long id);
41+
42+
void clearRequestHandlers();
3543
}

java/src/org/openqa/selenium/remote/RemoteNetwork.java

+111
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,28 @@
1818
package org.openqa.selenium.remote;
1919

2020
import java.net.URI;
21+
import java.util.ArrayList;
22+
import java.util.List;
2123
import java.util.Map;
2224
import java.util.Optional;
2325
import java.util.concurrent.ConcurrentHashMap;
2426
import java.util.concurrent.atomic.AtomicLong;
2527
import java.util.function.Predicate;
28+
import java.util.function.UnaryOperator;
2629
import org.openqa.selenium.Beta;
2730
import org.openqa.selenium.UsernameAndPassword;
2831
import org.openqa.selenium.WebDriver;
2932
import org.openqa.selenium.bidi.BiDi;
3033
import org.openqa.selenium.bidi.HasBiDi;
3134
import 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;
3238
import 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
3545
class 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
}

java/src/org/openqa/selenium/remote/http/HttpMethod.java

+13-1
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,17 @@ public enum HttpMethod {
2626
PATCH,
2727
HEAD,
2828
CONNECT,
29-
TRACE,
29+
TRACE;
30+
31+
public static HttpMethod getHttpMethod(String method) {
32+
if (method == null) {
33+
throw new IllegalArgumentException("Method cannot be null");
34+
}
35+
36+
try {
37+
return HttpMethod.valueOf(method.toUpperCase());
38+
} catch (IllegalArgumentException e) {
39+
throw new IllegalArgumentException("No enum constant for method: " + method);
40+
}
41+
}
3042
}

0 commit comments

Comments
 (0)