Skip to content

Commit 5cd4bd2

Browse files
[cdp][java] Allow filters to recover from failed requests in NetworkInterceptor (#13847)
Co-authored-by: Puja Jagani <puja.jagani93@gmail.com>
1 parent 4b41538 commit 5cd4bd2

File tree

3 files changed

+67
-3
lines changed

3 files changed

+67
-3
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium.devtools;
19+
20+
import org.openqa.selenium.WebDriverException;
21+
import org.openqa.selenium.remote.http.Filter;
22+
import org.openqa.selenium.remote.http.HttpHandler;
23+
24+
/**
25+
* This exception is thrown by the final {@link HttpHandler} in a {@link Filter} chain when the
26+
* browser fails to send a HTTP request. It can be caught in a {@link Filter} to handle the error
27+
* by, for example, returning a custom HTTP response.
28+
*/
29+
public class RequestFailedException extends WebDriverException {}

java/src/org/openqa/selenium/devtools/idealized/Network.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.openqa.selenium.devtools.DevToolsException;
4646
import org.openqa.selenium.devtools.Event;
4747
import org.openqa.selenium.devtools.NetworkInterceptor;
48+
import org.openqa.selenium.devtools.RequestFailedException;
4849
import org.openqa.selenium.internal.Either;
4950
import org.openqa.selenium.internal.Require;
5051
import org.openqa.selenium.remote.http.Contents;
@@ -202,8 +203,12 @@ public void prepareToInterceptTraffic() {
202203
String id = getRequestId(pausedRequest);
203204

204205
if (hasErrorResponse(pausedRequest)) {
205-
pendingResponses.remove(id);
206-
devTools.send(continueWithoutModification(pausedRequest));
206+
CompletableFuture<HttpResponse> future = pendingResponses.remove(id);
207+
if (future == null) {
208+
devTools.send(continueWithoutModification(pausedRequest));
209+
} else {
210+
future.completeExceptionally(new RequestFailedException());
211+
}
207212
return;
208213
}
209214

@@ -244,6 +249,11 @@ public void prepareToInterceptTraffic() {
244249
pendingResponses.remove(id);
245250
return STOP_PROCESSING;
246251
} catch (ExecutionException e) {
252+
if (e.getCause() instanceof RequestFailedException) {
253+
// Throwing here will give the user's filter a chance to intercept
254+
// the failure and handle it.
255+
throw (RequestFailedException) e.getCause();
256+
}
247257
if (fetchEnabled.get()) {
248258
LOG.log(WARNING, e, () -> "Unable to process request");
249259
}
@@ -261,6 +271,10 @@ public void prepareToInterceptTraffic() {
261271
}
262272

263273
devTools.send(fulfillRequest(pausedRequest, forBrowser));
274+
} catch (RequestFailedException e) {
275+
// If the exception reaches here, we know the user's filter has not handled it and the
276+
// browser should continue its normal error handling.
277+
devTools.send(continueWithoutModification(pausedRequest));
264278
} catch (TimeoutException e) {
265279
if (fetchEnabled.get()) {
266280
throw e;

java/test/org/openqa/selenium/devtools/NetworkInterceptorTest.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,11 +254,32 @@ void shouldHandleRedirects() {
254254

255255
@Test
256256
@NoDriverBeforeTest
257-
void shouldProceedAsNormalIfRequestResultInAnKnownError() {
257+
void shouldProceedAsNormalIfRequestResultInAnKnownErrorAndExceptionNotCaughtByFilter() {
258258
Filter filter = next -> next;
259259
try (NetworkInterceptor ignored = new NetworkInterceptor(driver, filter)) {
260260
assertThatExceptionOfType(WebDriverException.class)
261261
.isThrownBy(() -> driver.get("http://localhost:" + PortProber.findFreePort()));
262262
}
263263
}
264+
265+
@Test
266+
@NoDriverBeforeTest
267+
void shouldPassResponseBackToBrowserIfRequestResultsInAnKnownErrorAndExceptionCaughtByFilter() {
268+
Filter filter =
269+
next ->
270+
req -> {
271+
try {
272+
return next.execute(req);
273+
} catch (RequestFailedException e) {
274+
return new HttpResponse()
275+
.setStatus(200)
276+
.setContent(Contents.utf8String("Hello, World!"));
277+
}
278+
};
279+
try (NetworkInterceptor ignored = new NetworkInterceptor(driver, filter)) {
280+
driver.get("http://localhost:" + PortProber.findFreePort());
281+
String body = driver.findElement(By.tagName("body")).getText();
282+
assertThat(body).contains("Hello, World!");
283+
}
284+
}
264285
}

0 commit comments

Comments
 (0)