Skip to content

Commit 92b77b5

Browse files
committed
feat(codex): implement body size limit and logging for Codex responses
1 parent 7aadcf0 commit 92b77b5

3 files changed

Lines changed: 40 additions & 8 deletions

File tree

src/server/router.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::server::routes::{codex, geminicli};
88

99
use axum::{
1010
Router,
11-
extract::{DefaultBodyLimit, FromRef, Request},
11+
extract::{FromRef, Request},
1212
http::{HeaderName, StatusCode, Version, header::USER_AGENT},
1313
middleware::{self, Next},
1414
response::Response,
@@ -226,7 +226,5 @@ pub fn pollux_router(state: PolluxState) -> Router {
226226
.merge(codex)
227227
.fallback(not_found_handler)
228228
.with_state(state)
229-
// Set DefaultBodyLimit to 30 MiB for all routes
230-
.layer(DefaultBodyLimit::max(30 * 1024 * 1024))
231229
.layer(middleware::from_fn(access_log))
232230
}

src/server/routes/codex/mod.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
use crate::server::router::PolluxState;
22
use axum::{
33
Router,
4+
extract::{DefaultBodyLimit, Request},
5+
http::header::CONTENT_LENGTH,
6+
middleware::{self, Next},
7+
response::Response,
48
routing::{get, post},
59
};
10+
use tracing::debug;
611

712
pub mod extract;
813
pub mod handlers;
@@ -14,6 +19,8 @@ use crate::providers::codex::SUPPORTED_MODEL_NAMES;
1419
use pollux_schema::openai::OpenaiModelList;
1520
use std::sync::LazyLock;
1621

22+
const CODEX_RESPONSES_BODY_LIMIT_BYTES: usize = 100 * 1024 * 1024;
23+
1724
pub static CODEX_MODEL_LIST: LazyLock<OpenaiModelList> = LazyLock::new(|| {
1825
OpenaiModelList::from_model_names(SUPPORTED_MODEL_NAMES.iter().cloned(), "codex".to_string())
1926
});
@@ -25,11 +32,36 @@ pub struct CodexContext {
2532
pub model_mask: u64,
2633
}
2734

35+
async fn debug_codex_responses_body_size(req: Request, next: Next) -> Response {
36+
let content_length = req
37+
.headers()
38+
.get(CONTENT_LENGTH)
39+
.and_then(|value| value.to_str().ok())
40+
.and_then(|value| value.parse::<u64>().ok());
41+
42+
match content_length {
43+
Some(bytes) => {
44+
debug!(
45+
content_length_bytes = bytes,
46+
content_length_mib = format_args!("{:.2}", bytes as f64 / (1024.0 * 1024.0)),
47+
"Incoming Codex /responses request body size"
48+
);
49+
}
50+
None => {
51+
debug!("Incoming Codex /responses request body size unknown (no Content-Length)");
52+
}
53+
}
54+
55+
next.run(req).await
56+
}
57+
2858
pub fn router() -> Router<PolluxState> {
2959
Router::new()
3060
.route(
3161
"/codex/v1/responses",
32-
post(handlers::codex_response_handler),
62+
post(handlers::codex_response_handler)
63+
.layer(DefaultBodyLimit::max(CODEX_RESPONSES_BODY_LIMIT_BYTES))
64+
.layer(middleware::from_fn(debug_codex_responses_body_size)),
3365
)
3466
.route("/codex/v1/models", get(handlers::codex_models_handler))
3567
.route("/codex/resource:add", post(resource::codex_resource_add))

tests/codex_route_basic_tests.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ async fn codex_response_route_rejects_bad_requests_and_requires_key() {
119119
r#"{"error":{"code":"NO_CREDENTIAL","message":"No available credentials to process the request.","type":"NO_CREDENTIAL"}}"#
120120
);
121121

122-
// 5) correct key + oversized JSON body -> 413
122+
// 5) correct key + 30 MiB JSON body -> 503 (Codex endpoint limit is higher than 30 MiB)
123123
let oversized_input = "a".repeat(30 * 1024 * 1024 + 1024);
124124
let oversized_payload = format!(r#"{{"model":"{model}","input":"{oversized_input}"}}"#);
125125
let resp = app
@@ -135,14 +135,16 @@ async fn codex_response_route_rejects_bad_requests_and_requires_key() {
135135
)
136136
.await
137137
.expect("request failed");
138-
assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
138+
assert_eq!(resp.status(), StatusCode::SERVICE_UNAVAILABLE);
139139

140140
let body = to_bytes(resp.into_body(), usize::MAX)
141141
.await
142142
.expect("failed to read response body");
143143
let body_str = std::str::from_utf8(&body).expect("response body was not utf-8");
144-
assert!(body_str.contains(r#""code":"PAYLOAD_TOO_LARGE""#));
145-
assert!(body_str.contains(r#""message":"request body too large""#));
144+
assert_eq!(
145+
body_str,
146+
r#"{"error":{"code":"NO_CREDENTIAL","message":"No available credentials to process the request.","type":"NO_CREDENTIAL"}}"#
147+
);
146148

147149
// 6) GET /codex/v1/models: no key -> 401
148150
let resp = app

0 commit comments

Comments
 (0)