Skip to content

fix(e2e,chromedriverproxy): WebSocket/CDP scheme over a TLS-terminating ingress#286

Open
rgarcia wants to merge 2 commits into
mainfrom
fix/chromedriver-bidi-wss-ingress
Open

fix(e2e,chromedriverproxy): WebSocket/CDP scheme over a TLS-terminating ingress#286
rgarcia wants to merge 2 commits into
mainfrom
fix/chromedriver-bidi-wss-ingress

Conversation

@rgarcia

@rgarcia rgarcia commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

ChromeDriver BiDi and CDP over a TLS-terminating ingress (the hypeman :9224/:9222 ingresses; serve https/wss) were broken because the WebSocket/CDP URLs used the wrong scheme. Docker is plaintext (http/ws) so it never showed there. Validated in kernel-images-private #237: the full e2e suite (incl. all 5 TestBidi* and TestCDPProxyReconnect) now passes against the staging hypeman host over Tailscale.

Fixes

  1. server/e2e/container.goChromeDriverAddr only stripped http:// (returned https://host:9224 with scheme attached); ChromeDriverWSURL hardcoded ws:// (→ malformed ws://https://host:9224/session). Now strip any scheme and pick ws/wss from the ChromeDriver URL's transport.
  2. server/lib/chromedriverproxy/proxy.gorewriteWebSocketURL kept chromedriver's ws:// scheme, so the webSocketUrl from POST /session was unreachable through the TLS ingress. New clientWSScheme(r) returns wss when X-Forwarded-Proto: https (Caddy ingress) or r.TLS != nil; docker keeps ws. + regression test.
  3. server/e2e/e2e_cdp_reconnect_test.gofetchBrowserWebSocketURL hardcoded http:// for the CDP /json/version probe (fails against the TLS :9222 ingress). Derive the scheme from the CDP URL's transport (wss → https).

🤖 Generated with Claude Code


Note

Medium Risk
Touches session-creation URL rewriting and shared e2e URL builders used by BiDi/CDP tests; scope is limited to scheme/host correctness with regression tests, but wrong logic would break remote automation connectivity.

Overview
Fixes WebDriver-BiDi and CDP clients failing behind the hypeman TLS ingress (https/wss on :9224 and :9222) while leaving Docker plaintext (http/ws) behavior unchanged.

In chromedriverproxy, POST /session responses now rewrite capabilities.webSocketUrl to wss:// when the client reached the proxy via TLS (X-Forwarded-Proto: https or r.TLS), via new clientWSScheme and an updated rewriteWebSocketURL. A regression test covers the forwarded-proto path.

E2e helpers align with the same transport split: ChromeDriverAddr strips any URL scheme (not only http://), ChromeDriverWSURL chooses ws vs wss from an https:// ChromeDriver base URL, and fetchBrowserWebSocketURL uses https for /json/version when CDPURL() is wss://.

Reviewed by Cursor Bugbot for commit e4d51ec. Bugbot is set up for automated code reviews on this repo. Configure here.

…ing ingress

ChromeDriver WebDriver-BiDi over a TLS-terminating ingress (the hypeman
:9224 ingress; serves https/wss) was broken because the BiDi WebSocket
URLs used the wrong scheme. Docker is plaintext (http/ws) so it never
showed there.

Two shared-code fixes:

1. server/e2e/container.go:
   - ChromeDriverAddr only stripped "http://", so for an
     "https://host:9224" ChromeDriver URL it returned
     "https://host:9224" with the scheme still attached.
   - ChromeDriverWSURL hardcoded "ws://", producing the malformed
     "ws://https://host:9224/session".
   Fix: strip any scheme in ChromeDriverAddr; pick ws:// vs wss:// in
   ChromeDriverWSURL based on whether the ChromeDriver URL is https.

2. server/lib/chromedriverproxy/proxy.go:
   rewriteWebSocketURL kept chromedriver's ws:// scheme, so the
   webSocketUrl returned from POST /session was ws://host:9224/... —
   unreachable through the TLS ingress. Fix: a new clientWSScheme(r)
   helper returns wss when the request arrives with
   X-Forwarded-Proto: https (set by the Caddy ingress) or r.TLS != nil,
   and rewriteWebSocketURL applies it. Docker (plaintext, no forwarded
   proto) keeps ws://. Plus a regression test
   TestHandler_PostSession_WSSchemeFromForwardedProto.

Validated in kernel-images-private #237: all 5 TestBidi* (Selenium,
Puppeteer, HTTPSession, Vibium, WebSocket) now pass against the staging
hypeman host over Tailscale.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@firetiger-agent

Copy link
Copy Markdown

Created a monitoring plan for this PR.

What this PR does: Fixes WebDriver BiDi connections that were broken when accessed through the Hypeman TLS-terminating ingress — users automating with the BiDi protocol over the secure :9224 endpoint can now establish sessions successfully.

Intended effect:

  • webSocketUrl scheme in POST /session response: baseline was ws:// (wrong, unreachable through TLS ingress); confirmed working if wss:// is returned when X-Forwarded-Proto: https is present — directly verified by the new regression test TestHandler_PostSession_WSSchemeFromForwardedProto in CI.
  • Docker/plaintext path: baseline unchanged (ws://); confirmed working if Docker-backend BiDi tests (TestBidiHTTPSession, TestBidiPuppeteer, TestBidiVibium, TestBidiSelenium) continue to pass in CI.

Risks:

  • Docker-path regression — Docker BiDi tests in CI; alert if any of TestBidiHTTPSession / TestBidiPuppeteer / TestBidiVibium / TestBidiSelenium fails post-merge.
  • X-Forwarded-Proto header absent at ingress — would silently fall back to ws:// (original broken state); no in-VM OTEL signal exists, but recurrence surfaces as BiDi session failures for users on the Hypeman ingress. Confirm Caddy ingress header injection is in place on first post-deploy BiDi session attempt.
  • POST /browsers 500 spike — baseline 0–2/hr; alert if sustained >10/hr for 2+ consecutive hours post image rollout (check opentelemetry/logs/api error count by hour).

Status updates will be posted automatically on this PR as monitoring progresses.

View monitor

fetchBrowserWebSocketURL hardcoded http:// for the CDP /json/version probe, so
it failed against a TLS-terminating CDP ingress (an http:// request hits a TLS
listener and errors); plaintext (docker) works. Derive the HTTP scheme from the
CDP URL's transport (wss -> https, ws -> http), matching the ChromeDriver
accessor scheme handling in this PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rgarcia rgarcia changed the title fix(chromedriverproxy,e2e): BiDi WebSocket scheme over a TLS-terminating ingress fix(e2e,chromedriverproxy): WebSocket/CDP scheme over a TLS-terminating ingress Jun 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant