Migrate login HTTP construction to HttpClient (#34643)

## Why

`codex-http-client` is the intended owner of direct `reqwest` usage.

## What changed

- Build Codex's default and route-aware clients with `HttpClientBuilder`, and return `HttpClient` directly to API, model discovery, auth, remote control, skills, and extension callers.
- Preserve custom CA, proxy, Cloudflare cookie, sandbox, and request-logging policies while removing `codex-login`'s direct `reqwest` dependency.
- Use shared HTTP types for auth headers, status codes, transport errors, and login-server tests.

## Testing

- Add a Linux integration test verifying that a regular Responses API turn traverses the configured system proxy.

GitOrigin-RevId: 714695fb80762d2083e2f7a6414183e2b3b63854
This commit is contained in:
Michael Bolin authored and copyberry committed 2026-07-22 00:50:28 +00:00
1 parent c5eb33aed1
commit 539c0e1100
21 files changed
+210 -131

No files matched your search

+12 -11
View File
@@ -9,6 +9,7 @@ use std::time::Duration;
use anyhow::Result;
use base64::Engine;
use codex_config::types::AuthCredentialsStoreMode;
use codex_http_client::HttpClientBuilder;
use codex_login::AuthKeyringBackendKind;
use codex_login::LoginSuccessPage;
use codex_login::LoginSuccessPageBrand;
@@ -145,9 +146,9 @@ async fn end_to_end_login_flow_persists_auth_json() -> Result<()> {
let login_port = server.actual_port;
// Simulate browser callback and assert the local success redirect before following it.
let client = reqwest::Client::builder()
.redirect(reqwest::redirect::Policy::none())
.build()?;
let client = HttpClientBuilder::new()
.without_redirects()
.build_direct()?;
let url = format!("http://127.0.0.1:{login_port}/auth/callback?code=abc&state=test_state_123");
let resp = client.get(&url).send().await?;
assert_eq!(resp.status(), 302);
@@ -204,9 +205,9 @@ async fn hosted_login_redirects_to_configured_open_app_url() -> Result<()> {
auth_keyring_backend_kind: AuthKeyringBackendKind::Direct,
})?;
let login_port = server.actual_port;
let client = reqwest::Client::builder()
.redirect(reqwest::redirect::Policy::none())
.build()?;
let client = HttpClientBuilder::new()
.without_redirects()
.build_direct()?;
let response = client
.get(format!(
@@ -256,7 +257,7 @@ async fn creates_missing_codex_home_dir() -> Result<()> {
let server = run_login_server(opts)?;
let login_port = server.actual_port;
let client = reqwest::Client::new();
let client = HttpClientBuilder::new().build_direct()?;
let url = format!("http://127.0.0.1:{login_port}/auth/callback?code=abc&state=state2");
let resp = client.get(&url).send().await?;
assert!(resp.status().is_success());
@@ -349,7 +350,7 @@ async fn forced_chatgpt_workspace_id_mismatch_blocks_login() -> Result<()> {
);
let login_port = server.actual_port;
let client = reqwest::Client::new();
let client = HttpClientBuilder::new().build_direct()?;
let url = format!("http://127.0.0.1:{login_port}/auth/callback?code=abc&state={state}");
let resp = client.get(&url).send().await?;
assert!(resp.status().is_success());
@@ -406,7 +407,7 @@ async fn oauth_access_denied_missing_entitlement_blocks_login_with_clear_error()
let server = run_login_server(opts)?;
let login_port = server.actual_port;
let client = reqwest::Client::new();
let client = HttpClientBuilder::new().build_direct()?;
let url = format!(
"http://127.0.0.1:{login_port}/auth/callback?state={state}&error=access_denied&error_description=missing_codex_entitlement"
);
@@ -477,7 +478,7 @@ async fn oauth_access_denied_unknown_reason_uses_generic_error_page() -> Result<
let server = run_login_server(opts)?;
let login_port = server.actual_port;
let client = reqwest::Client::new();
let client = HttpClientBuilder::new().build_direct()?;
let url = format!(
"http://127.0.0.1:{login_port}/auth/callback?state={state}&error=access_denied&error_description=some_other_reason"
);
@@ -658,7 +659,7 @@ async fn cancels_previous_login_server_when_port_is_in_use() -> Result<()> {
.expect_err("login server should report cancellation");
assert_eq!(cancel_result.kind(), io::ErrorKind::Interrupted);
let client = reqwest::Client::new();
let client = HttpClientBuilder::new().build_direct()?;
let cancel_url = format!("http://127.0.0.1:{login_port}/cancel");
let resp = client.get(cancel_url).send().await?;
assert!(resp.status().is_success());