Skip to content

[🐛 Bug]: NetworkInterceptor overwrites failed requests with 200 response #13774

@joebandenburg

Description

@joebandenburg

What happened?

I've been using NetworkInterceptor successfully with Chrome to add headers to requests. However, I've run into an edge case where NetworkInterceptor does the wrong thing.

If the request fails by not returning a response (e.g. there's a timeout or the hostname does not exist), Selenium replaces the response with a empty 200 response and returns that to Chrome. This causes Chrome to load an empty page rather than failing.

As you can see from the logs below, the second Fetch.requestPaused message from Chrome contains "responseErrorReason":"NameNotResolved". After this Selenium sends an inappropriate Fetch.getResponseBody, which fails. Selenium constructs an empty 200 response and passes that back to the user's filter. Whatever that filter return is then sent via a Fetch.fulfillRequest call. As far as I can tell, there is no way for the user's filter to distinguish one of these fake 200 responses for a real 200 response (other than the fact that the response is otherwise empty).

I'm not entirely sure how Selenium should handle this error but sending a Fetch.continueRequest seems to make sense and makes the behaviour consistent to how Selenium behaves if the NetworkInterceptor has not been used. i.e. the web driver will throw a WebDriverException from driver.get.

The faulty logic seems to be in v123Network#createSeMessages. It checks to see if responseErrorReason is set but otherwise ignores the value, continuing on to try to fetch the response body. When that fails, it assumes the reason for such a failure is due to a redirect response, at which point an empty 200 response is constructed.

How can we reproduce the issue?

WebDriver driver = ...
Filter filter = next -> next;
try (var ignored = new NetworkInterceptor(driver, filter)) {
  // This should raise an exception, but doesn't!
  driver.get("https://fakesite.pro/en/index.html");
  // The web browser has loaded an empty page, even though fakesite.pro doesn't exist.
}

Relevant log output

2024-04-03T12:53:33.759-04:00  INFO 33243 --- [ CDP Connection] o.openqa.selenium.devtools.Connection    : <- {"method":"Fetch.requestPaused","params":{"requestId":"interception-job-1.0","request":{"url":"https://fakesite.pro/en/index.html","method":"GET","headers":{"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Accept-Language":"en-GB,en-US;q=0.9,en;q=0.8","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"},"initialPriority":"VeryHigh","referrerPolicy":"strict-origin-when-cross-origin"},"frameId":"618FD10968BEC9788FF3163BFDE85FAD","resourceType":"Document"},"sessionId":"F9C647A6D0F886EAE174C7CFD101EF46"}
2024-04-03T12:53:33.760-04:00  INFO 33243 --- [ CDP Connection] o.openqa.selenium.devtools.Connection    : Method Fetch.requestPaused called with 2 callbacks available
2024-04-03T12:53:33.760-04:00  INFO 33243 --- [ CDP Connection] o.openqa.selenium.devtools.Connection    : Matching Fetch.requestPaused with Fetch.requestPaused
2024-04-03T12:53:33.762-04:00  INFO 33243 --- [ CDP Connection] o.openqa.selenium.devtools.Connection    : Calling callback for Fetch.requestPaused using org.openqa.selenium.devtools.idealized.Network$$Lambda/0x000000050184e7b8@34b31eb3 being passed org.openqa.selenium.devtools.v123.fetch.model.RequestPaused@14ca5f7b
2024-04-03T12:53:33.763-04:00  INFO 33243 --- [ CDP Connection] o.openqa.selenium.devtools.Connection    : -> {
  "id": 7,
  "sessionId": "F9C647A6D0F886EAE174C7CFD101EF46",
  "method": "Fetch.continueRequest",
  "params": {
    "postData": "",
    "requestId": "interception-job-1.0",
    "method": "GET",
    "headers": [
      {
        "name": "Accept",
        "value": "text\u002fhtml,application\u002fxhtml+xml,application\u002fxml;q=0.9,image\u002favif,image\u002fwebp,image\u002fapng,*\u002f*;q=0.8,application\u002fsigned-exchange;v=b3;q=0.7"
      },
      {
        "name": "Upgrade-Insecure-Requests",
        "value": "1"
      },
      {
        "name": "User-Agent",
        "value": "Mozilla\u002f5.0 (X11; Linux x86_64) AppleWebKit\u002f537.36 (KHTML, like Gecko) Chrome\u002f123.0.0.0 Safari\u002f537.36"
      },
      {
        "name": "Accept-Language",
        "value": "en-GB,en-US;q=0.9,en;q=0.8"
      }
    ],
    "url": "https:\u002f\u002ffakesite.pro\u002fen\u002findex.html"
  }
}
2024-04-03T12:53:33.766-04:00  INFO 33243 --- [ CDP Connection] o.openqa.selenium.devtools.Connection    : <- {"id":7,"result":{},"sessionId":"F9C647A6D0F886EAE174C7CFD101EF46"}
2024-04-03T12:53:33.777-04:00  INFO 33243 --- [ CDP Connection] o.openqa.selenium.devtools.Connection    : <- {"method":"Fetch.requestPaused","params":{"requestId":"interception-job-1.0","request":{"url":"https://fakesite.pro/en/index.html","method":"GET","headers":{"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Accept-Language":"en-GB,en-US;q=0.9,en;q=0.8","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"},"initialPriority":"VeryHigh","referrerPolicy":"strict-origin-when-cross-origin"},"frameId":"618FD10968BEC9788FF3163BFDE85FAD","resourceType":"Document","responseErrorReason":"NameNotResolved"},"sessionId":"F9C647A6D0F886EAE174C7CFD101EF46"}
2024-04-03T12:53:33.778-04:00  INFO 33243 --- [ CDP Connection] o.openqa.selenium.devtools.Connection    : Method Fetch.requestPaused called with 2 callbacks available
2024-04-03T12:53:33.778-04:00  INFO 33243 --- [ CDP Connection] o.openqa.selenium.devtools.Connection    : Matching Fetch.requestPaused with Fetch.requestPaused
2024-04-03T12:53:33.778-04:00  INFO 33243 --- [ CDP Connection] o.openqa.selenium.devtools.Connection    : Calling callback for Fetch.requestPaused using org.openqa.selenium.devtools.idealized.Network$$Lambda/0x000000050184e7b8@34b31eb3 being passed org.openqa.selenium.devtools.v123.fetch.model.RequestPaused@744853f6
2024-04-03T12:53:33.779-04:00  INFO 33243 --- [ CDP Connection] o.openqa.selenium.devtools.Connection    : -> {
  "id": 8,
  "sessionId": "F9C647A6D0F886EAE174C7CFD101EF46",
  "method": "Fetch.getResponseBody",
  "params": {
    "requestId": "interception-job-1.0"
  }
}
2024-04-03T12:53:33.781-04:00  INFO 33243 --- [ CDP Connection] o.openqa.selenium.devtools.Connection    : <- {"id":8,"error":{"code":-32000,"message":"Can only get response body on requests captured after headers received."},"sessionId":"F9C647A6D0F886EAE174C7CFD101EF46"}
2024-04-03T12:53:33.782-04:00  INFO 33243 --- [ CDP Connection] o.openqa.selenium.devtools.Connection    : Matching Fetch.requestPaused with Fetch.authRequired
2024-04-03T12:53:33.783-04:00  INFO 33243 --- [ CDP Connection] o.openqa.selenium.devtools.Connection    : -> {
  "id": 9,
  "sessionId": "F9C647A6D0F886EAE174C7CFD101EF46",
  "method": "Fetch.fulfillRequest",
  "params": {
    "responseHeaders": [
    ],
    "body": "",
    "requestId": "interception-job-1.0",
    "responseCode": 200
  }
}
2024-04-03T12:53:33.785-04:00  INFO 33243 --- [ CDP Connection] o.openqa.selenium.devtools.Connection    : <- {"id":9,"result":{},"sessionId":"F9C647A6D0F886EAE174C7CFD101EF46"}

Operating System

macOS Sonoma 14.4.1

Selenium version

Java 4.19.1

What are the browser(s) and version(s) where you see this issue?

Chrome 123.0

What are the browser driver(s) and version(s) where you see this issue?

ChromeDriver 123.0

Are you using Selenium Grid?

4.19.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-needs-triagingA Selenium member will evaluate this soon!B-devtoolsIncludes everything BiDi or Chrome DevTools relatedC-javaJava BindingsI-defectSomething is not working as intended

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions