Skip to content

Classify upstream proxy rejections by status code, not message text - #59

Merged
jochen-testingbot merged 1 commit into
mainfrom
fix-flaky-connect-framing-test
Oct 2, 2026
Merged

jochen-testingbot merged 1 commit into
mainfrom
fix-flaky-connect-framing-test

Conversation

@jochen-testingbot

Copy link
Copy Markdown
Contributor

Fixes the flaky ConnectFramingTest.aRejectionFromTheUpstreamProxyIsNotReportedAsSuccess (failed on 2026-09-25 and on #58's first CI run).

Cause

The failing response from CI:

X-TestingBot-Error: upstream-proxy-auth-failed

The stand-in proxy answered 403 Forbidden. ProxyErrors.classifyOne treated any message containing proxy and 407 as a credentials failure, and the message includes the proxy's port, which that run was 40797.

The test was right; the product was wrong. A proxy on a port like 3407 or 14070 has every refusal reported to users as upstream-proxy-auth-failed. A SOCKS refusal whose destination is named like credentials.example.com was misread the same way.

Fix

  • New UpstreamProxyRejection extends IOException carries the parsed HTTP status. Thrown for a non-2xx CONNECT reply (CustomConnectHandler, WebsocketHandler) and for a proxy declining a get-mode WebSocket upgrade.
  • ProxyErrors classifies it by the number: 407 gives upstream-proxy-auth-failed, anything else gives upstream-proxy-refused.
  • For SOCKS, which still matches on text, the refusal check now runs before the credentials check, which is what its comment already said it did.

WebsocketThroughProxyTest asserts upstream-proxy-refused against a random port too, so it had the same latent flake.

Tests

Three new ProxyErrorsTest cases. Run against the old classifier, two of them fail, reproducing the 40797 case and the hostname case deterministically. With the fix, mvn verify passes: 1005 tests, coverage gate met.

ConnectFramingTest.aRejectionFromTheUpstreamProxyIsNotReportedAsSuccess
failed about one CI run in fifty. The stand-in proxy answered 403 and the
tunnel reported upstream-proxy-auth-failed: ProxyErrors searched the
exception message for "407", and the message names the proxy's port,
which that run was 40797.

The test was right and the product was wrong. A real proxy on a port like
3407 had every refusal reported as rejected credentials, sending the
operator to check a password that was fine. A SOCKS refusal naming a host
such as credentials.example.com was misread the same way.

An HTTP proxy's non-2xx answer is now an UpstreamProxyRejection carrying
the parsed status, classified on the number: 407 is an auth failure and
anything else is a refusal. This covers CONNECT, the WebSocket CONNECT
reply and the get-mode upgrade. The remaining text matching, for SOCKS,
checks for a refusal first, as its comment already claimed it did.
@jochen-testingbot
jochen-testingbot merged commit 318f84d into main Oct 2, 2026
10 checks passed
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