Migrate direct HTTP consumers to codex-http-client (#31331)

## Why

#31323 introduces `codex-http-client` and leaves compatibility
re-exports in `codex-client`. Low-level HTTP consumers should depend on
the crate that now owns those APIs rather than continuing through the
transitional compatibility layer.

This stacked follow-up makes that ownership explicit and moves the
repository toward enforcing the abstraction without mixing call-site
churn into the extraction itself.

## What changed

- Switched `codex-backend-client`, `codex-cloud-tasks`,
`codex-exec-server`, `codex-login`, and `codex-model-provider` from
`codex-client` to `codex-http-client` where they only use low-level HTTP
APIs.
- Added the direct dependency to `codex-api` for its custom-CA request
and websocket paths while retaining `codex-client` for higher-level
retry and transport policy.
- Updated imports and normalized login's internal client type name from
`CodexHttpClient` to `HttpClient`, while preserving its existing
`CodexRequestBuilder` re-export.
- Updated `Cargo.lock` to reflect the new direct dependency edges.

## Review guide

This PR is intentionally mechanical: 20 files and 92 changed lines, with
no runtime logic changes. The largest diff is
`codex-rs/login/src/auth/default_client.rs`, where the only
semantic-looking changes are type and import renames. The remaining
source changes replace `codex_client` import paths with
`codex_http_client`; the manifest and lockfile changes mirror those
imports.

## Test plan

- Compile-checked `codex-api`, `codex-backend-client`,
`codex-cloud-tasks`, `codex-exec-server`, `codex-login`, and
`codex-model-provider` together.
This commit is contained in:
Michael Bolin
2026-07-07 01:34:36 +00:00
committed by GitHub
parent 9acfe8965d
commit 641aa1b619
20 changed files with 47 additions and 45 deletions
+6 -5
View File
@@ -1936,6 +1936,7 @@ dependencies = [
"bytes",
"chrono",
"codex-client",
"codex-http-client",
"codex-protocol",
"codex-utils-rustls-provider",
"eventsource-stream",
@@ -2262,7 +2263,7 @@ dependencies = [
"anyhow",
"codex-api",
"codex-backend-openapi-models",
"codex-client",
"codex-http-client",
"codex-login",
"codex-model-provider",
"codex-protocol",
@@ -2431,11 +2432,11 @@ dependencies = [
"anyhow",
"chrono",
"clap",
"codex-client",
"codex-cloud-tasks-client",
"codex-cloud-tasks-mock-client",
"codex-core",
"codex-git-utils",
"codex-http-client",
"codex-login",
"codex-model-provider",
"codex-tui",
@@ -2895,9 +2896,9 @@ dependencies = [
"bytes",
"clatter",
"codex-api",
"codex-client",
"codex-exec-server-protocol",
"codex-file-system",
"codex-http-client",
"codex-network-proxy",
"codex-otel",
"codex-protocol",
@@ -3315,8 +3316,8 @@ dependencies = [
"base64 0.22.1",
"chrono",
"codex-agent-identity",
"codex-client",
"codex-config",
"codex-http-client",
"codex-keyring-store",
"codex-model-provider-info",
"codex-otel",
@@ -3530,8 +3531,8 @@ dependencies = [
"codex-agent-identity",
"codex-api",
"codex-aws-auth",
"codex-client",
"codex-feedback",
"codex-http-client",
"codex-login",
"codex-model-provider-info",
"codex-models-manager",
+1 -1
View File
@@ -19,7 +19,7 @@ serde_json = "1"
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
codex-backend-openapi-models = { path = "../codex-backend-openapi-models" }
codex-api = { workspace = true }
codex-client = { workspace = true }
codex-http-client = { workspace = true }
codex-login = { workspace = true }
codex-model-provider = { workspace = true }
codex-protocol = { workspace = true }
+2 -2
View File
@@ -9,8 +9,8 @@ use crate::types::TokenUsageProfile;
use crate::types::TurnAttemptsSiblingTurnsResponse;
use anyhow::Result;
use codex_api::SharedAuthProvider;
use codex_client::build_reqwest_client_with_custom_ca;
use codex_client::with_chatgpt_cloudflare_cookie_store;
use codex_http_client::build_reqwest_client_with_custom_ca;
use codex_http_client::with_chatgpt_cloudflare_cookie_store;
use codex_login::CodexAuth;
use codex_login::default_client::get_codex_user_agent;
use codex_protocol::account::PlanType as AccountPlanType;
+1 -1
View File
@@ -16,7 +16,7 @@ workspace = true
anyhow = { workspace = true }
chrono = { workspace = true, features = ["serde"] }
clap = { workspace = true, features = ["derive"] }
codex-client = { workspace = true }
codex-http-client = { workspace = true }
codex-cloud-tasks-client = { workspace = true }
# TODO: codex-cloud-tasks-mock-client should be in dev-dependencies.
codex-cloud-tasks-mock-client = { workspace = true }
+1 -1
View File
@@ -1,4 +1,4 @@
use codex_client::build_reqwest_client_with_custom_ca;
use codex_http_client::build_reqwest_client_with_custom_ca;
use reqwest::header::CONTENT_TYPE;
use reqwest::header::HeaderMap;
use std::collections::HashMap;
+1
View File
@@ -10,6 +10,7 @@ base64 = { workspace = true }
bytes = { workspace = true }
chrono = { workspace = true }
codex-client = { workspace = true }
codex-http-client = { workspace = true }
codex-protocol = { workspace = true }
codex-utils-rustls-provider = { workspace = true }
futures = { workspace = true }
@@ -16,7 +16,7 @@ use crate::endpoint::realtime_websocket::protocol::parse_realtime_event;
use crate::error::ApiError;
use crate::provider::Provider;
use codex_client::backoff;
use codex_client::maybe_build_rustls_client_config_with_custom_ca;
use codex_http_client::maybe_build_rustls_client_config_with_custom_ca;
use codex_protocol::protocol::ConversationTextRole;
use codex_protocol::protocol::RealtimeTranscriptDelta;
use codex_utils_rustls_provider::ensure_rustls_crypto_provider;
@@ -11,7 +11,7 @@ use crate::sse::ResponsesStreamEvent;
use crate::sse::process_responses_event;
use crate::telemetry::WebsocketTelemetry;
use codex_client::TransportError;
use codex_client::maybe_build_rustls_client_config_with_custom_ca;
use codex_http_client::maybe_build_rustls_client_config_with_custom_ca;
use codex_utils_rustls_provider::ensure_rustls_crypto_provider;
use futures::SinkExt;
use futures::StreamExt;
+1 -1
View File
@@ -2,7 +2,7 @@ use std::time::Duration;
use crate::AuthProvider;
use bytes::Bytes;
use codex_client::build_reqwest_client_with_custom_ca;
use codex_http_client::build_reqwest_client_with_custom_ca;
use futures::Stream;
use reqwest::StatusCode;
use reqwest::header::CONTENT_LENGTH;
+1 -1
View File
@@ -17,7 +17,7 @@ base64 = { workspace = true }
bytes = { workspace = true }
clatter = { workspace = true }
codex-api = { workspace = true }
codex-client = { workspace = true }
codex-http-client = { workspace = true }
codex-exec-server-protocol = { workspace = true }
codex-file-system = { workspace = true }
codex-network-proxy = { workspace = true }
@@ -8,9 +8,9 @@
use std::error::Error as StdError;
use std::time::Duration;
use codex_client::build_reqwest_client_with_custom_ca;
use codex_client::with_chatgpt_cloudflare_cookie_store;
use codex_exec_server_protocol::JSONRPCErrorError;
use codex_http_client::build_reqwest_client_with_custom_ca;
use codex_http_client::with_chatgpt_cloudflare_cookie_store;
use futures::FutureExt;
use futures::StreamExt;
use futures::future::BoxFuture;
+1 -1
View File
@@ -11,7 +11,7 @@ workspace = true
base64 = { workspace = true }
chrono = { workspace = true, features = ["serde"] }
codex-agent-identity = { workspace = true }
codex-client = { workspace = true }
codex-http-client = { workspace = true }
codex-config = { workspace = true }
codex-keyring-store = { workspace = true }
codex-model-provider-info = { workspace = true }
+13 -13
View File
@@ -1,17 +1,17 @@
//! Default Codex HTTP client: shared `User-Agent`, `originator`, optional residency header, and
//! reqwest/`CodexHttpClient` construction.
//! reqwest/`HttpClient` construction.
//!
//! Use [`crate::default_client`] or [`codex_login::default_client`] from other crates in this
//! workspace.
use codex_client::BuildCustomCaTransportError;
use codex_client::BuildRouteAwareHttpClientError;
use codex_client::ClientRouteClass;
use codex_client::CodexHttpClient;
pub use codex_client::CodexRequestBuilder;
use codex_client::build_reqwest_client_for_route;
use codex_client::build_reqwest_client_with_custom_ca;
use codex_client::with_chatgpt_cloudflare_cookie_store;
use codex_http_client::BuildCustomCaTransportError;
use codex_http_client::BuildRouteAwareHttpClientError;
use codex_http_client::ClientRouteClass;
use codex_http_client::HttpClient;
pub use codex_http_client::RequestBuilder as CodexRequestBuilder;
use codex_http_client::build_reqwest_client_for_route;
use codex_http_client::build_reqwest_client_with_custom_ca;
use codex_http_client::with_chatgpt_cloudflare_cookie_store;
use codex_terminal_detection::user_agent;
use reqwest::header::HeaderMap;
use reqwest::header::HeaderValue;
@@ -197,9 +197,9 @@ fn sanitize_user_agent(candidate: String, fallback: &str) -> String {
///
/// This supported default path preserves reqwest's existing proxy behavior and does not opt into
/// Codex's route-aware system/PAC resolution.
pub fn create_client() -> CodexHttpClient {
pub fn create_client() -> HttpClient {
let inner = build_reqwest_client();
CodexHttpClient::new(inner)
HttpClient::new(inner)
}
/// Builds the default reqwest client used for ordinary Codex HTTP traffic.
@@ -282,8 +282,8 @@ pub(crate) fn build_default_auth_reqwest_client(
pub(crate) fn create_default_auth_client(
endpoint: &str,
auth_route_config: Option<&AuthRouteConfig>,
) -> Result<CodexHttpClient, BuildRouteAwareHttpClientError> {
build_default_auth_reqwest_client(endpoint, auth_route_config).map(CodexHttpClient::new)
) -> Result<HttpClient, BuildRouteAwareHttpClientError> {
build_default_auth_reqwest_client(endpoint, auth_route_config).map(HttpClient::new)
}
pub fn default_headers() -> HeaderMap {
+4 -4
View File
@@ -55,8 +55,8 @@ use crate::outbound_proxy::AuthRouteConfig;
use crate::token_data::TokenData;
use crate::token_data::parse_chatgpt_jwt_claims;
use crate::token_data::parse_jwt_expiration;
use codex_client::CodexHttpClient;
use codex_config::types::AuthCredentialsStoreMode;
use codex_http_client::HttpClient;
use codex_protocol::account::PlanType as AccountPlanType;
use codex_protocol::auth::PlanType as InternalPlanType;
use codex_protocol::auth::RefreshTokenFailedError;
@@ -171,7 +171,7 @@ pub struct ChatgptAuthTokens {
#[derive(Debug, Clone)]
struct ChatgptAuthState {
auth_dot_json: Arc<Mutex<Option<AuthDotJson>>>,
client: CodexHttpClient,
client: HttpClient,
}
const TOKEN_REFRESH_INTERVAL: i64 = 8;
@@ -805,7 +805,7 @@ impl ChatgptAuth {
&self.storage
}
fn client(&self) -> &CodexHttpClient {
fn client(&self) -> &HttpClient {
&self.state.client
}
@@ -1331,7 +1331,7 @@ fn persist_tokens(
// The caller is responsible for persisting any returned tokens.
async fn request_chatgpt_token_refresh(
refresh_token: String,
client: &CodexHttpClient,
client: &HttpClient,
) -> Result<RefreshResponse, RefreshTokenError> {
let refresh_request = RefreshRequest {
client_id: oauth_client_id(),
@@ -1,4 +1,4 @@
use codex_client::CodexHttpClient;
use codex_http_client::HttpClient;
use codex_protocol::account::PlanType as AccountPlanType;
use codex_protocol::auth::PlanType as InternalPlanType;
use serde::Deserialize;
@@ -77,7 +77,7 @@ impl PersonalAccessTokenAuth {
}
async fn hydrate_personal_access_token(
client: &CodexHttpClient,
client: &HttpClient,
endpoint: &str,
access_token: &str,
) -> std::io::Result<PersonalAccessTokenAuth> {
+3 -3
View File
@@ -7,7 +7,7 @@
use serde::Serialize;
use std::time::Duration;
use codex_client::CodexHttpClient;
use codex_http_client::HttpClient;
use codex_protocol::auth::AuthMode;
use super::manager::REFRESH_TOKEN_URL_OVERRIDE_ENV_VAR;
@@ -95,7 +95,7 @@ fn resolved_auth_mode(auth_dot_json: &AuthDotJson) -> AuthMode {
}
async fn revoke_oauth_token(
client: &CodexHttpClient,
client: &HttpClient,
endpoint: &str,
token: &str,
kind: RevokeTokenKind,
@@ -181,7 +181,7 @@ mod tests {
.mount(&server)
.await;
let client = CodexHttpClient::new(reqwest::Client::new());
let client = HttpClient::new(reqwest::Client::new());
let endpoint = format!("{}/oauth/revoke", server.uri());
let error = revoke_oauth_token(
&client,
+1 -1
View File
@@ -7,8 +7,8 @@ mod outbound_proxy;
mod pkce;
mod server;
pub use codex_client::BuildCustomCaTransportError as BuildLoginHttpClientError;
pub use codex_config::types::AuthCredentialsStoreMode;
pub use codex_http_client::BuildCustomCaTransportError as BuildLoginHttpClientError;
pub use device_code_auth::DeviceCode;
pub use device_code_auth::complete_device_code_login;
pub use device_code_auth::request_device_code;
+1 -1
View File
@@ -1,4 +1,4 @@
use codex_client::OutboundProxyConfig;
use codex_http_client::OutboundProxyConfig;
/// Auth-layer adapter around client-owned proxy policy.
///
+1 -1
View File
@@ -16,7 +16,7 @@ workspace = true
codex-api = { workspace = true }
codex-agent-identity = { workspace = true }
codex-aws-auth = { workspace = true }
codex-client = { workspace = true }
codex-http-client = { workspace = true }
codex-feedback = { workspace = true }
codex-login = { workspace = true }
codex-model-provider-info = { workspace = true }
@@ -6,9 +6,9 @@ use codex_api::SharedAuthProvider;
use codex_aws_auth::AwsAuthContext;
use codex_aws_auth::AwsAuthError;
use codex_aws_auth::AwsRequestToSign;
use codex_client::Request;
use codex_client::RequestBody;
use codex_client::RequestCompression;
use codex_http_client::Request;
use codex_http_client::RequestBody;
use codex_http_client::RequestCompression;
use codex_login::auth::BedrockApiKeyAuth;
use codex_model_provider_info::ModelProviderAwsAuthInfo;
use codex_protocol::error::CodexErr;