Skip to content

Commit

Permalink
[cdp][java] Allow filters to recover from failed requests in NetworkI…
Browse files Browse the repository at this point in the history
…nterceptor (#13847)

Co-authored-by: Puja Jagani <[email protected]>
  • Loading branch information
joebandenburg and pujagani authored May 7, 2024
1 parent 4b41538 commit 5cd4bd2
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 3 deletions.
29 changes: 29 additions & 0 deletions java/src/org/openqa/selenium/devtools/RequestFailedException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package org.openqa.selenium.devtools;

import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.remote.http.Filter;
import org.openqa.selenium.remote.http.HttpHandler;

/**
* This exception is thrown by the final {@link HttpHandler} in a {@link Filter} chain when the
* browser fails to send a HTTP request. It can be caught in a {@link Filter} to handle the error
* by, for example, returning a custom HTTP response.
*/
public class RequestFailedException extends WebDriverException {}
18 changes: 16 additions & 2 deletions java/src/org/openqa/selenium/devtools/idealized/Network.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.openqa.selenium.devtools.DevToolsException;
import org.openqa.selenium.devtools.Event;
import org.openqa.selenium.devtools.NetworkInterceptor;
import org.openqa.selenium.devtools.RequestFailedException;
import org.openqa.selenium.internal.Either;
import org.openqa.selenium.internal.Require;
import org.openqa.selenium.remote.http.Contents;
Expand Down Expand Up @@ -202,8 +203,12 @@ public void prepareToInterceptTraffic() {
String id = getRequestId(pausedRequest);

if (hasErrorResponse(pausedRequest)) {
pendingResponses.remove(id);
devTools.send(continueWithoutModification(pausedRequest));
CompletableFuture<HttpResponse> future = pendingResponses.remove(id);
if (future == null) {
devTools.send(continueWithoutModification(pausedRequest));
} else {
future.completeExceptionally(new RequestFailedException());
}
return;
}

Expand Down Expand Up @@ -244,6 +249,11 @@ public void prepareToInterceptTraffic() {
pendingResponses.remove(id);
return STOP_PROCESSING;
} catch (ExecutionException e) {
if (e.getCause() instanceof RequestFailedException) {
// Throwing here will give the user's filter a chance to intercept
// the failure and handle it.
throw (RequestFailedException) e.getCause();
}
if (fetchEnabled.get()) {
LOG.log(WARNING, e, () -> "Unable to process request");
}
Expand All @@ -261,6 +271,10 @@ public void prepareToInterceptTraffic() {
}

devTools.send(fulfillRequest(pausedRequest, forBrowser));
} catch (RequestFailedException e) {
// If the exception reaches here, we know the user's filter has not handled it and the
// browser should continue its normal error handling.
devTools.send(continueWithoutModification(pausedRequest));
} catch (TimeoutException e) {
if (fetchEnabled.get()) {
throw e;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,32 @@ void shouldHandleRedirects() {

@Test
@NoDriverBeforeTest
void shouldProceedAsNormalIfRequestResultInAnKnownError() {
void shouldProceedAsNormalIfRequestResultInAnKnownErrorAndExceptionNotCaughtByFilter() {
Filter filter = next -> next;
try (NetworkInterceptor ignored = new NetworkInterceptor(driver, filter)) {
assertThatExceptionOfType(WebDriverException.class)
.isThrownBy(() -> driver.get("http://localhost:" + PortProber.findFreePort()));
}
}

@Test
@NoDriverBeforeTest
void shouldPassResponseBackToBrowserIfRequestResultsInAnKnownErrorAndExceptionCaughtByFilter() {
Filter filter =
next ->
req -> {
try {
return next.execute(req);
} catch (RequestFailedException e) {
return new HttpResponse()
.setStatus(200)
.setContent(Contents.utf8String("Hello, World!"));
}
};
try (NetworkInterceptor ignored = new NetworkInterceptor(driver, filter)) {
driver.get("http://localhost:" + PortProber.findFreePort());
String body = driver.findElement(By.tagName("body")).getText();
assertThat(body).contains("Hello, World!");
}
}
}

0 comments on commit 5cd4bd2

Please sign in to comment.