Skip to content

core: use HTTP Responses with system proxy#31342

Draft
bolinfest wants to merge 1 commit into
mainfrom
pr31342
Draft

core: use HTTP Responses with system proxy#31342
bolinfest wants to merge 1 commit into
mainfrom
pr31342

Conversation

@bolinfest

@bolinfest bolinfest commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Why

#31335 routes the HTTP Responses endpoints through the proxy-aware client factory, but Responses WebSockets still dial directly through tokio-tungstenite. Because WebSocket-capable providers are preferred for normal turns, a session with features.respect_system_proxy could still attempt direct egress before falling back to HTTP.

Until codex-http-client owns proxy-aware WebSocket dialing, the conservative behavior is to keep system-proxy sessions on the HTTP transport that already honors the resolved policy.

What changed

  • Treat Responses WebSockets as unavailable when the session's HttpClientFactory uses OutboundProxyPolicy::RespectSystemProxy.
  • Reuse the existing responses_websocket_enabled() gate, so startup preconnect, prewarm, and turn-time connection paths all avoid a direct WebSocket handshake.
  • Add an integration test with a WebSocket-capable provider and the real feature configuration. It verifies that the server receives zero WebSocket upgrade requests and one successful HTTP /responses request.
  • Leave ReqwestDefault sessions unchanged.

Review guide

  1. core/src/client.rs contains the policy gate shared by every Responses WebSocket entry point.
  2. core/tests/suite/websocket_fallback.rs proves that a WebSocket-capable provider goes directly to HTTP when the system-proxy policy is active.

Follow-up

Add proxy-aware WebSocket dialing, including HTTP CONNECT support, to codex-http-client; then remove this conservative gate and route Responses WebSockets through the same factory.

Test plan

  • cargo check -p codex-core --tests
  • New integration coverage: system_proxy_policy_uses_http_without_websocket_handshake

Stack created with Sapling. Best reviewed with ReviewStack.

@bolinfest bolinfest changed the base branch from main to pr31335 July 7, 2026 02:45
Base automatically changed from pr31335 to main July 7, 2026 03:49
bolinfest added a commit that referenced this pull request Jul 7, 2026
## Why

`features.respect_system_proxy` already routes authentication traffic
through the OS proxy APIs, but it does not affect the primary inference
path. That leaves users behind OS-managed proxies unable to send normal
Responses API requests even after login succeeds.

This PR is the first product-path migration onto the route-aware
transport introduced in #31323 and refined in #31331. It also
establishes the construction pattern for later migrations: the effective
feature state is resolved once into a required HTTP client factory
rather than represented by an optional per-call setting.

The scope remains limited to the two HTTP Responses endpoints;
WebSockets, model discovery, memories, realtime, and file uploads remain
follow-up migrations.

## What changed

- Replace the optional proxy marker with an explicit
`OutboundProxyPolicy::{ReqwestDefault, RespectSystemProxy}` and a
required `HttpClientFactory`. The policy has no default, and the
lower-level route-aware reqwest builder is now private.
- Have `Config` construct the factory from the effective feature state
and require every `ModelClient` constructor to receive it. There is no
optional setter or implicit `None` fallback.
- Build HTTP clients for `/responses` and `/responses/compact` with
`ClientRouteClass::Api`, using the complete destination URL so PAC rules
can make URL-specific decisions.
- Layer route-aware selection onto Codex's existing default headers,
Cloudflare cookie store, custom CA handling, and sandbox no-proxy
behavior.
- Add an integration test that loads `features.respect_system_proxy`
through `config.toml`, creates a real Codex session, and verifies that
both a normal Responses turn and remote compaction reach an isolated
local proxy.

## Review guide

1. `http-client/src/outbound_proxy.rs` defines the mandatory
policy/factory boundary and keeps route resolution private.
2. `core/src/config/mod.rs`, `core/src/session/session.rs`, and
`core/src/client.rs` show the compile-time invariant: effective config
creates the factory, and `ModelClient` cannot be constructed without
one.
3. `login/src/auth/default_client.rs` preserves existing default-client
behavior while accepting the required factory for migrated routes.
4. `core/src/client.rs` switches only streaming Responses and remote
compaction HTTP transports to the API route class.
5. `core/tests/suite/responses_api_system_proxy.rs` is the behavioral
regression boundary. Its Linux subprocess deliberately sets the CGI
marker that disables reqwest's implicit environment-proxy handling, so
the test fails if session wiring or either Responses call site falls
back to the default client.

## Test plan

- `cargo check --tests -p codex-http-client -p codex-login -p
codex-core`
- `just test -p codex-login`
- `just test -p codex-core
respect_system_proxy_feature_resolves_enabled`
- Existing `compact_uses_bearer_after_agent_identity_session_fallback`
coverage passes with the new transport construction.
- New Linux integration coverage:
`responses_and_compact_use_enabled_system_proxy`
- `just bazel-lock-check`

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/31335).
* #31342
* __->__ #31335
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