Skip to content

core: preserve Responses WebSockets with system proxy#31441

Draft
bolinfest wants to merge 1 commit into
mainfrom
pr31441
Draft

core: preserve Responses WebSockets with system proxy#31441
bolinfest wants to merge 1 commit into
mainfrom
pr31441

Conversation

@bolinfest

@bolinfest bolinfest commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Why

Responses WebSockets are the normal lower-latency transport for WebSocket-capable providers. They must not bypass an OS-selected proxy when features.respect_system_proxy is enabled, but disabling WebSockets whenever the feature is enabled would impose a substantial performance penalty.

Building on #31342, this change keeps the WebSocket fast path while applying the same concrete route and trust policy as HTTP.

What changed

  • Require a configured HttpClientFactory for Responses WebSocket connections and the CLI doctor probe, so callers cannot open this transport without consulting the effective proxy policy.
  • Add a route-aware WebSocket connector:
    • DIRECT opens the target TCP connection without falling through to environment proxy discovery.
    • HTTP and HTTPS proxies establish a CONNECT tunnel before the target TLS/WebSocket handshake; TLS-encrypted proxies and the target share the custom-CA-aware rustls configuration.
    • Transport-default routing preserves tokio-tungstenite's existing environment-proxy handling when the feature is disabled or platform resolution is unavailable.
  • Preserve tokio-tungstenite's Happy Eyeballs behavior for explicit direct and proxy routes so an unreachable address family does not add a connection-timeout regression.
  • Type-erase the routed network stream only after connection setup so the existing Responses WebSocket pump and session-scoped HTTP fallback remain unchanged.
  • Keep proxy URLs redacted in invalid-configuration errors.

Review guide

  1. codex-api/src/websocket_connector.rs owns direct dialing, proxy TLS/CONNECT, target TLS, and Happy Eyeballs.
  2. codex-api/src/websocket_connector_tests.rs exercises explicit direct routing plus HTTP and HTTPS proxies with real WSS/TLS handshakes.
  3. codex-api/src/endpoint/responses_websocket.rs makes the factory mandatory and adapts the established stream to the existing pump.
  4. core/src/client.rs and cli/src/doctor.rs pass their effective factories into the Responses WebSocket API.

Test plan

  • cargo check --tests -p codex-http-client -p codex-api -p codex-core -p codex-cli
  • just test -p codex-api websocket_connector
  • just bazel-lock-check

Stack created with Sapling. Best reviewed with ReviewStack.

@bolinfest bolinfest changed the base branch from main to pr31342 July 7, 2026 17:35
bolinfest added a commit that referenced this pull request Jul 7, 2026
## Why

#31335 lets HTTP callers obtain proxy-aware clients from
`HttpClientFactory`, but a non-HTTP transport such as WebSockets also
needs two pieces of policy owned by `codex-http-client`: a concrete
route decision for its destination and the same custom-CA-aware rustls
trust configuration used by HTTPS.

Keeping these prerequisites in the shared abstraction means the
dependent Responses WebSocket change (#31441) cannot independently
reinterpret `features.respect_system_proxy`, PAC results, or enterprise
CA settings.

## What changed

- Add a redaction-safe `OutboundProxyRoute` with explicit
transport-default, direct, and concrete-proxy outcomes.
- Add `HttpClientFactory::resolve_proxy_route()` so transports can
resolve a destination through the already-selected outbound proxy
policy.
- Resolve `ws://` and `wss://` URLs through their HTTP equivalents so
system and PAC rules apply consistently.
- Add an always-returned rustls config builder that starts from native
roots and layers in any configured Codex custom CA bundle. The existing
optional builder remains available to callers that can delegate the
default configuration to their transport.
- Continue redacting proxy URLs from `Debug` output because they may
contain credentials.

## Review guide

1. `http-client/src/outbound_proxy.rs` defines the transport-neutral
route result and WebSocket URL normalization.
2. `http-client/src/custom_ca.rs` factors the native-root/custom-CA
construction so callers that perform TLS themselves can always obtain a
config.
3. `http-client/src/outbound_proxy_tests.rs` verifies WebSocket
normalization and legacy transport-default behavior.

## Test plan

- `just test -p codex-http-client outbound_proxy`
- `just test -p codex-http-client custom_ca`

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/31342).
* #31431
* #31363
* #31362
* #31361
* #31442
* #31441
* __->__ #31342
Base automatically changed from pr31342 to main July 7, 2026 22:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant