mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
api: send hyphenated session and thread headers (#21757)
## Why Some consumers expect conventional hyphenated HTTP headers. Codex already sends the session and thread IDs on outbound Responses requests, but it only uses the underscore spellings today, which makes those IDs harder to consume in systems that normalize or reject underscore header names. Full context here: https://openai.slack.com/archives/C08KCGLSPSQ/p1778248578422369 ## What changed - `build_session_headers` now emits both `session_id` and `session-id` when a session ID is present. - It does the same for `thread_id` and `thread-id`. - Added regression coverage in `codex-api/tests/clients.rs` and `core/tests/suite/client.rs` so both the lower-level client tests and the end-to-end request tests assert the two header spellings are present. ## Test plan - Added header assertions in `codex-api/tests/clients.rs`. - Added request-header assertions in `core/tests/suite/client.rs` for both the `/v1/responses` and `/api/codex/responses` request paths.
This commit is contained in:
committed by
GitHub
Unverified
parent
e6312d44f0
commit
bd8fc9adb9
@@ -6,9 +6,11 @@ pub fn build_session_headers(session_id: Option<String>, thread_id: Option<Strin
|
||||
let mut headers = HeaderMap::new();
|
||||
if let Some(id) = session_id {
|
||||
insert_header(&mut headers, "session_id", &id);
|
||||
insert_header(&mut headers, "session-id", &id);
|
||||
}
|
||||
if let Some(id) = thread_id {
|
||||
insert_header(&mut headers, "thread_id", &id);
|
||||
insert_header(&mut headers, "thread-id", &id);
|
||||
}
|
||||
headers
|
||||
}
|
||||
|
||||
@@ -462,10 +462,18 @@ async fn azure_default_store_attaches_ids_and_headers() -> Result<()> {
|
||||
req.headers.get("session_id").and_then(|v| v.to_str().ok()),
|
||||
Some("sess_123")
|
||||
);
|
||||
assert_eq!(
|
||||
req.headers.get("session-id").and_then(|v| v.to_str().ok()),
|
||||
Some("sess_123")
|
||||
);
|
||||
assert_eq!(
|
||||
req.headers.get("thread_id").and_then(|v| v.to_str().ok()),
|
||||
Some("thread_123")
|
||||
);
|
||||
assert_eq!(
|
||||
req.headers.get("thread-id").and_then(|v| v.to_str().ok()),
|
||||
Some("thread_123")
|
||||
);
|
||||
assert_eq!(
|
||||
req.headers
|
||||
.get("x-client-request-id")
|
||||
|
||||
@@ -764,7 +764,9 @@ async fn includes_session_id_thread_id_and_model_headers_in_request() {
|
||||
let request = resp_mock.single_request();
|
||||
assert_eq!(request.path(), "/v1/responses");
|
||||
let request_session_id = request.header("session_id").expect("session_id header");
|
||||
let request_session_id_hyphenated = request.header("session-id").expect("session-id header");
|
||||
let request_thread_id = request.header("thread_id").expect("thread_id header");
|
||||
let request_thread_id_hyphenated = request.header("thread-id").expect("thread-id header");
|
||||
let request_authorization = request
|
||||
.header("authorization")
|
||||
.expect("authorization header");
|
||||
@@ -776,7 +778,12 @@ async fn includes_session_id_thread_id_and_model_headers_in_request() {
|
||||
let thread_id_string = expected_thread_id.to_string();
|
||||
|
||||
assert_eq!(request_session_id, expected_session_id.to_string());
|
||||
assert_eq!(
|
||||
request_session_id_hyphenated,
|
||||
expected_session_id.to_string()
|
||||
);
|
||||
assert_eq!(request_thread_id, thread_id_string.as_str());
|
||||
assert_eq!(request_thread_id_hyphenated, thread_id_string.as_str());
|
||||
assert_eq!(request_originator, originator().value);
|
||||
assert_eq!(request_authorization, "Bearer Test API Key");
|
||||
assert_eq!(
|
||||
@@ -1038,12 +1045,19 @@ async fn chatgpt_auth_sends_correct_request() {
|
||||
let request_body = request.body_json();
|
||||
|
||||
let request_session_id = request.header("session_id").expect("session_id header");
|
||||
let request_session_id_hyphenated = request.header("session-id").expect("session-id header");
|
||||
let request_thread_id = request.header("thread_id").expect("thread_id header");
|
||||
let request_thread_id_hyphenated = request.header("thread-id").expect("thread-id header");
|
||||
let installation_id =
|
||||
std::fs::read_to_string(test.codex_home_path().join(INSTALLATION_ID_FILENAME))
|
||||
.expect("read installation id");
|
||||
assert_eq!(request_session_id, expected_session_id.to_string());
|
||||
assert_eq!(
|
||||
request_session_id_hyphenated,
|
||||
expected_session_id.to_string()
|
||||
);
|
||||
assert_eq!(request_thread_id, expected_thread_id.to_string());
|
||||
assert_eq!(request_thread_id_hyphenated, expected_thread_id.to_string());
|
||||
|
||||
assert_eq!(request_originator, originator().value);
|
||||
assert_eq!(request_authorization, "Bearer Access Token");
|
||||
|
||||
@@ -177,15 +177,24 @@ trust_level = "trusted"
|
||||
}
|
||||
};
|
||||
let output_text = String::from_utf8_lossy(&output);
|
||||
let interrupt_only_output = {
|
||||
let trimmed_output = output_text.trim();
|
||||
!trimmed_output.is_empty()
|
||||
&& trimmed_output
|
||||
let rendered_output = {
|
||||
let mut parser = vt100::Parser::new(
|
||||
/*rows*/ 24, /*cols*/ 80, /*scrollback_len*/ 0,
|
||||
);
|
||||
parser.process(&output);
|
||||
parser.screen().contents()
|
||||
};
|
||||
let interrupted_during_terminal_startup = {
|
||||
let trimmed_output = rendered_output.trim();
|
||||
trimmed_output.is_empty()
|
||||
|| trimmed_output
|
||||
.chars()
|
||||
.all(|character| character == '^' || character == 'C' || character.is_whitespace())
|
||||
};
|
||||
anyhow::ensure!(
|
||||
exit_code == 0 || exit_code == 130 || (exit_code == 1 && interrupt_only_output),
|
||||
exit_code == 0
|
||||
|| exit_code == 130
|
||||
|| (exit_code == 1 && interrupted_during_terminal_startup),
|
||||
"unexpected exit code from codex resume: {exit_code}; output: {output_text}",
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user