feat(network-proxy): add websocket proxy env support (#11784)

## Summary
- add managed proxy env wiring for websocket-specific variables
(`WS_PROXY`/`WSS_PROXY`, including lowercase)
- keep websocket proxy vars aligned with the existing managed HTTP proxy
endpoint
- add CONNECT regression tests to cover allowlist and denylist decisions
(websocket tunnel path)
- document websocket proxy usage and CONNECT policy behavior in the
network proxy README

## Testing
- just fmt
- cargo test -p codex-network-proxy
- cargo clippy -p codex-network-proxy

Co-authored-by: Codex <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
This commit is contained in:
viyatb-oai
2026-02-17 13:49:43 -08:00
committed by GitHub
parent ad53574d58
commit f2ad519a87
3 changed files with 80 additions and 0 deletions

View File

@@ -828,6 +828,51 @@ mod tests {
);
}
#[tokio::test]
async fn http_connect_accept_allows_allowlisted_host_in_full_mode() {
let policy = NetworkProxySettings {
allowed_domains: vec!["example.com".to_string()],
..Default::default()
};
let state = Arc::new(network_proxy_state_for_policy(policy));
let mut req = Request::builder()
.method(Method::CONNECT)
.uri("https://example.com:443")
.header("host", "example.com:443")
.body(Body::empty())
.unwrap();
req.extensions_mut().insert(state);
let (response, _request) = http_connect_accept(None, req).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);
}
#[tokio::test]
async fn http_connect_accept_denies_denylisted_host() {
let policy = NetworkProxySettings {
allowed_domains: vec!["**.openai.com".to_string()],
denied_domains: vec!["api.openai.com".to_string()],
..Default::default()
};
let state = Arc::new(network_proxy_state_for_policy(policy));
let mut req = Request::builder()
.method(Method::CONNECT)
.uri("https://api.openai.com:443")
.header("host", "api.openai.com:443")
.body(Body::empty())
.unwrap();
req.extensions_mut().insert(state);
let response = http_connect_accept(None, req).await.unwrap_err();
assert_eq!(response.status(), StatusCode::FORBIDDEN);
assert_eq!(
response.headers().get("x-proxy-error").unwrap(),
"blocked-by-denylist"
);
}
#[test]
fn request_network_attempt_id_reads_proxy_authorization_header() {
let encoded = STANDARD.encode("codex-net-attempt-attempt-1:");