diff --git a/codex-rs/codex-api/src/endpoint/responses_websocket.rs b/codex-rs/codex-api/src/endpoint/responses_websocket.rs index 16a0151690..f887edd56c 100644 --- a/codex-rs/codex-api/src/endpoint/responses_websocket.rs +++ b/codex-rs/codex-api/src/endpoint/responses_websocket.rs @@ -7,6 +7,7 @@ use crate::common::WS_REQUEST_HEADER_TRACEPARENT_CLIENT_METADATA_KEY; use crate::error::ApiError; use crate::provider::Provider; use crate::rate_limits::parse_rate_limit_event; +use crate::responses_headers::json_headers_to_http_headers; use crate::safety_buffering::treatment_from_headers; use crate::sse::ResponsesStreamEvent; use crate::sse::process_responses_event; @@ -18,8 +19,6 @@ use codex_websocket_client::WebSocketConnector; use futures::SinkExt; use futures::StreamExt; use http::HeaderMap; -use http::HeaderName; -use http::HeaderValue; use http::StatusCode; use serde::Deserialize; use serde_json::Value; @@ -660,30 +659,6 @@ fn map_wrapped_websocket_error_event( })) } -fn json_headers_to_http_headers(headers: &JsonMap) -> HeaderMap { - let mut mapped = HeaderMap::new(); - for (name, value) in headers { - let Ok(header_name) = HeaderName::from_bytes(name.as_bytes()) else { - continue; - }; - let Some(header_value) = json_header_value(value) else { - continue; - }; - mapped.insert(header_name, header_value); - } - mapped -} - -fn json_header_value(value: &Value) -> Option { - let value = match value { - Value::String(value) => value.clone(), - Value::Number(value) => value.to_string(), - Value::Bool(value) => value.to_string(), - _ => return None, - }; - HeaderValue::from_str(&value).ok() -} - async fn run_websocket_response_stream( ws_stream: &mut WsStream, tx_event: mpsc::Sender>, @@ -930,6 +905,7 @@ mod tests { use codex_protocol::ResponseItemId; use codex_protocol::models::ContentItem; use codex_protocol::models::ResponseItem; + use http::HeaderValue; use pretty_assertions::assert_eq; use serde_json::json; use serde_json::value::RawValue; diff --git a/codex-rs/codex-api/src/lib.rs b/codex-rs/codex-api/src/lib.rs index 05df1c2708..b7511d9e50 100644 --- a/codex-rs/codex-api/src/lib.rs +++ b/codex-rs/codex-api/src/lib.rs @@ -8,6 +8,7 @@ pub(crate) mod images; pub(crate) mod provider; pub(crate) mod rate_limits; pub(crate) mod requests; +mod responses_headers; pub(crate) mod safety_buffering; pub(crate) mod search; pub(crate) mod sse; diff --git a/codex-rs/codex-api/src/responses_headers.rs b/codex-rs/codex-api/src/responses_headers.rs new file mode 100644 index 0000000000..3bde074256 --- /dev/null +++ b/codex-rs/codex-api/src/responses_headers.rs @@ -0,0 +1,32 @@ +//! Converts headers in Responses event payloads to HTTP headers. +//! Invalid names and unsupported or invalid values are ignored. + +use http::HeaderMap; +use http::HeaderName; +use http::HeaderValue; +use serde_json::Value; +use serde_json::map::Map as JsonMap; + +pub(crate) fn json_headers_to_http_headers(headers: &JsonMap) -> HeaderMap { + let mut mapped = HeaderMap::new(); + for (name, value) in headers { + let Ok(header_name) = HeaderName::from_bytes(name.as_bytes()) else { + continue; + }; + let Some(header_value) = json_header_value(value) else { + continue; + }; + mapped.insert(header_name, header_value); + } + mapped +} + +fn json_header_value(value: &Value) -> Option { + let value = match value { + Value::String(value) => value.clone(), + Value::Number(value) => value.to_string(), + Value::Bool(value) => value.to_string(), + _ => return None, + }; + HeaderValue::from_str(&value).ok() +}