mirror of
https://github.com/openai/codex.git
synced 2026-09-04 15:08:45 +00:00
core: use HTTP Responses with system proxy
This commit is contained in:
@@ -64,6 +64,7 @@ use codex_api::create_text_param_for_request;
|
||||
use codex_api::response_create_client_metadata;
|
||||
use codex_http_client::ClientRouteClass;
|
||||
use codex_http_client::HttpClientFactory;
|
||||
use codex_http_client::OutboundProxyPolicy;
|
||||
use codex_login::AuthManager;
|
||||
use codex_login::CodexAuth;
|
||||
use codex_login::RefreshTokenError;
|
||||
@@ -912,9 +913,14 @@ impl ModelClient {
|
||||
|
||||
/// Returns whether the Responses-over-WebSocket transport is active for this session.
|
||||
///
|
||||
/// WebSocket use is controlled by provider capability and session-scoped fallback state.
|
||||
/// WebSocket use is controlled by outbound proxy policy, provider capability, and
|
||||
/// session-scoped fallback state. System-proxy sessions conservatively use HTTP until the
|
||||
/// WebSocket transport supports proxy-aware dialing.
|
||||
pub fn responses_websocket_enabled(&self) -> bool {
|
||||
if !self.state.provider.info().supports_websockets
|
||||
if matches!(
|
||||
self.http_client_factory.outbound_proxy_policy(),
|
||||
OutboundProxyPolicy::RespectSystemProxy
|
||||
) || !self.state.provider.info().supports_websockets
|
||||
|| self.state.disable_websockets.load(Ordering::Relaxed)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use codex_config::CONFIG_TOML_FILE;
|
||||
use codex_model_provider_info::WireApi;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
@@ -26,6 +27,60 @@ use wiremock::http::Method;
|
||||
use wiremock::matchers::method;
|
||||
use wiremock::matchers::path_regex;
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn system_proxy_policy_uses_http_without_websocket_handshake() -> Result<()> {
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let server = responses::start_mock_server().await;
|
||||
let response_mock = mount_sse_once(
|
||||
&server,
|
||||
sse(vec![ev_response_created("resp-1"), ev_completed("resp-1")]),
|
||||
)
|
||||
.await;
|
||||
|
||||
let mut builder = test_codex()
|
||||
.with_pre_build_hook(|codex_home| {
|
||||
std::fs::write(
|
||||
codex_home.join(CONFIG_TOML_FILE),
|
||||
"[features]\nrespect_system_proxy = true\n",
|
||||
)
|
||||
.expect("system-proxy feature config should be written");
|
||||
})
|
||||
.with_config({
|
||||
let base_url = format!("{}/v1", server.uri());
|
||||
move |config| {
|
||||
config.model_provider.base_url = Some(base_url);
|
||||
config.model_provider.wire_api = WireApi::Responses;
|
||||
config.model_provider.supports_websockets = true;
|
||||
config.model_provider.request_max_retries = Some(0);
|
||||
}
|
||||
});
|
||||
let test = builder.build_with_auto_env(&server).await?;
|
||||
assert!(test.config.respect_system_proxy);
|
||||
|
||||
test.submit_turn("hello").await?;
|
||||
|
||||
let requests = server.received_requests().await.unwrap_or_default();
|
||||
let websocket_attempts = requests
|
||||
.iter()
|
||||
.filter(|request| {
|
||||
request.method == Method::GET && request.url.path().ends_with("/responses")
|
||||
})
|
||||
.count();
|
||||
let http_attempts = requests
|
||||
.iter()
|
||||
.filter(|request| {
|
||||
request.method == Method::POST && request.url.path().ends_with("/responses")
|
||||
})
|
||||
.count();
|
||||
|
||||
assert_eq!(websocket_attempts, 0);
|
||||
assert_eq!(http_attempts, 1);
|
||||
assert_eq!(response_mock.requests().len(), 1);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn websocket_fallback_switches_to_http_on_upgrade_required_connect() -> Result<()> {
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
Reference in New Issue
Block a user