mirror of
https://github.com/openai/codex.git
synced 2026-10-23 18:08:45 +00:00
## What changed - Add `OAuthSessionRequest` to pair access tokens with their authorization identity and retain rejected-token recovery across transient failures and retries. New sign-ins receive an identity that survives token refresh. - Expose explicit login, logout, and authorization identity lookup, plus a per-manager option to disable automatic browser login while allowing credential reuse and refresh. - Move serializable `OAuthSessionConfig` into `codex-model-provider-info`, add an optional `device_authorization_url` field, and share endpoint URL validation through `codex-http-client`. - Distinguish permission failures, transient token endpoint failures, and invalid responses using `io::ErrorKind`. ## Testing Add coverage for sign-in identity preservation through refresh retries, removal of saved and cached credentials on logout, and suppression of automatic browser login. Extend token endpoint error classification coverage. GitOrigin-RevId: ae9f72e787171e179fe139a3b840a9f7e1e46506
112 lines
4.1 KiB
Rust
112 lines
4.1 KiB
Rust
use url::Host;
|
|
use url::Url;
|
|
|
|
mod chatgpt_cloudflare_cookies;
|
|
mod chatgpt_hosts;
|
|
mod client;
|
|
mod client_builder;
|
|
mod client_tls;
|
|
mod custom_ca;
|
|
mod error;
|
|
mod native_roots;
|
|
mod network_policy;
|
|
mod outbound_proxy;
|
|
mod request;
|
|
mod request_builder;
|
|
mod request_draft;
|
|
mod response;
|
|
mod retry_after;
|
|
mod route_aware_client_pool;
|
|
mod route_aware_redirect;
|
|
mod tls_backend_fallback;
|
|
mod transport;
|
|
|
|
pub use crate::chatgpt_cloudflare_cookies::with_chatgpt_cloudflare_cookie_store;
|
|
pub use crate::chatgpt_hosts::is_allowed_chatgpt_host;
|
|
pub use crate::client::HttpClient;
|
|
pub use crate::client::HttpError;
|
|
pub use crate::client_builder::HttpClientBuilder;
|
|
pub use crate::client_tls::HttpClientTlsConfig;
|
|
pub use crate::custom_ca::BuildCustomCaTransportError;
|
|
/// Test-only subprocess hook for custom CA coverage.
|
|
///
|
|
/// This stays public only so the `custom_ca_probe` binary target can reuse the shared helper. It
|
|
/// is hidden from normal docs because ordinary callers should use
|
|
/// [`build_reqwest_client_with_custom_ca`] instead.
|
|
#[doc(hidden)]
|
|
pub use crate::custom_ca::build_reqwest_client_for_subprocess_tests;
|
|
pub use crate::custom_ca::build_reqwest_client_with_custom_ca;
|
|
pub use crate::custom_ca::build_rustls_client_config_with_custom_ca;
|
|
pub use crate::custom_ca::maybe_build_rustls_client_config_with_custom_ca;
|
|
pub use crate::error::StreamError;
|
|
pub use crate::error::TransportError;
|
|
pub use crate::network_policy::DestinationPolicy;
|
|
pub use crate::network_policy::NetworkPermit;
|
|
pub use crate::network_policy::NetworkPolicy;
|
|
pub use crate::network_policy::NetworkPolicyController;
|
|
pub use crate::network_policy::NetworkPolicyDenied;
|
|
pub use crate::network_policy::NetworkPolicyRevision;
|
|
pub use crate::outbound_proxy::BuildRouteAwareHttpClientError;
|
|
pub use crate::outbound_proxy::ClientRouteClass;
|
|
pub use crate::outbound_proxy::HttpClientFactory;
|
|
#[cfg(target_os = "macos")]
|
|
pub use crate::outbound_proxy::MacosSystemProxyConfiguration;
|
|
pub use crate::outbound_proxy::OutboundProxyPolicy;
|
|
pub use crate::outbound_proxy::OutboundProxyRoute;
|
|
pub use crate::outbound_proxy::RouteFailureClass;
|
|
#[doc(hidden)]
|
|
pub use crate::outbound_proxy::cache_system_proxy_route_for_test;
|
|
#[cfg(target_os = "macos")]
|
|
pub use crate::outbound_proxy::macos_system_proxy_configuration;
|
|
pub use crate::request::EncodedJsonBody;
|
|
pub use crate::request::PreparedRequestBody;
|
|
pub use crate::request::Request;
|
|
pub use crate::request::RequestBody;
|
|
pub use crate::request::RequestCompression;
|
|
pub use crate::request::Response;
|
|
pub use crate::request_builder::RequestBuilder;
|
|
pub use crate::response::HttpResponse;
|
|
pub use crate::retry_after::RetryAfter;
|
|
pub use crate::route_aware_client_pool::RouteAwareClientPool;
|
|
pub use crate::route_aware_client_pool::RouteAwareClientPoolError;
|
|
pub use crate::route_aware_client_pool::RouteAwareRequestError;
|
|
pub use crate::transport::ByteStream;
|
|
pub use crate::transport::HttpTransport;
|
|
pub use crate::transport::ReqwestTransport;
|
|
pub use crate::transport::StreamResponse;
|
|
|
|
#[cfg(windows)]
|
|
mod windows_proxy_auth;
|
|
#[cfg(windows)]
|
|
mod windows_tls;
|
|
|
|
#[cfg(windows)]
|
|
pub use crate::windows_proxy_auth::WindowsProxyTls;
|
|
#[cfg(windows)]
|
|
pub use crate::windows_proxy_auth::connect_windows_proxy;
|
|
#[cfg(windows)]
|
|
pub use crate::windows_tls::build_windows_platform_tls_config;
|
|
|
|
/// Validates HTTPS or loopback HTTP endpoints, rejecting userinfo and fragments.
|
|
/// Errors identify the caller-supplied field without including the URL.
|
|
pub fn validate_endpoint_url(value: &str, field: &str) -> Result<Url, String> {
|
|
let url = Url::parse(value).map_err(|_| format!("invalid {field} URL"))?;
|
|
let loopback = match url.host() {
|
|
Some(Host::Domain(host)) => host.eq_ignore_ascii_case("localhost"),
|
|
Some(Host::Ipv4(host)) => host.is_loopback(),
|
|
Some(Host::Ipv6(host)) => host.is_loopback(),
|
|
None => false,
|
|
};
|
|
if url.host().is_none()
|
|
|| !url.username().is_empty()
|
|
|| url.password().is_some()
|
|
|| url.fragment().is_some()
|
|
|| !(url.scheme() == "https" || (url.scheme() == "http" && loopback))
|
|
{
|
|
return Err(format!(
|
|
"{field} must use HTTPS (or loopback HTTP), without userinfo or a fragment"
|
|
));
|
|
}
|
|
Ok(url)
|
|
}
|