From c372c9972983e8d48bc97ab358633958a27202b7 Mon Sep 17 00:00:00 2001 From: CPU-216 <3125034290@stu.cpu.edu.cn> Date: Thu, 12 Mar 2026 08:03:12 +0800 Subject: [PATCH] fix(test): stabilize openai compat oversized-body regression (#839) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(test): stabilize openai compat oversized-body regression * docs(web): fix stale body limit in CLAUDE.md (1 MB → 10 MB) CLAUDE.md:200 still documented the pre-#725 body limit of 1 MB, but server.rs:354 was changed to 10 MB in #725 (image upload support). Update the documentation to match the actual production value. --- src/channels/web/CLAUDE.md | 2 +- tests/openai_compat_integration.rs | 48 ++++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/channels/web/CLAUDE.md b/src/channels/web/CLAUDE.md index df5cd6cf..8db9a6b7 100644 --- a/src/channels/web/CLAUDE.md +++ b/src/channels/web/CLAUDE.md @@ -197,7 +197,7 @@ All responses include: - `X-Content-Type-Options: nosniff` - `X-Frame-Options: DENY` -**Request body limit:** 1 MB (`DefaultBodyLimit::max(1024 * 1024)`). Larger payloads return 413. +**Request body limit:** 10 MB (`DefaultBodyLimit::max(10 * 1024 * 1024)`), sized for image uploads (#725). Larger payloads return 413. ## Pending Approvals diff --git a/tests/openai_compat_integration.rs b/tests/openai_compat_integration.rs index c6dd9a11..939f39eb 100644 --- a/tests/openai_compat_integration.rs +++ b/tests/openai_compat_integration.rs @@ -729,21 +729,45 @@ async fn test_no_llm_provider_returns_503() { #[tokio::test] async fn test_chat_completions_body_too_large() { - let (addr, _state, _mock_state) = start_test_server().await; - let url = format!("http://{}/v1/chat/completions", addr); + use axum::{Router, body::Body, extract::DefaultBodyLimit, middleware, routing::post}; + use tower::ServiceExt; - // Build a payload over 10 MB (the gateway's DefaultBodyLimit) + let mock_state = Arc::new(MockLlmState::default()); + let llm_provider: Arc = Arc::new(MockLlmProvider::new(mock_state)); + let state = ironclaw::channels::web::test_helpers::TestGatewayBuilder::new() + .llm_provider(llm_provider) + .build(); + let auth_state = ironclaw::channels::web::auth::AuthState { + token: AUTH_TOKEN.to_string(), + }; + + let app = Router::new() + .route( + "/v1/chat/completions", + post(ironclaw::channels::web::openai_compat::chat_completions_handler), + ) + .route_layer(middleware::from_fn_with_state( + auth_state, + ironclaw::channels::web::auth::auth_middleware, + )) + .layer(DefaultBodyLimit::max(10 * 1024 * 1024)) + .with_state(state); + + // Build a payload over 10 MB (the gateway's DefaultBodyLimit). let big_content = "x".repeat(11 * 1024 * 1024); - let resp = client() - .post(&url) - .bearer_auth(AUTH_TOKEN) - .json(&serde_json::json!({ - "model": "mock-model-v1", - "messages": [{"role": "user", "content": big_content}] - })) - .send() - .await + let body = serde_json::to_vec(&serde_json::json!({ + "model": "mock-model-v1", + "messages": [{"role": "user", "content": big_content}] + })) + .unwrap(); + let req = axum::http::Request::builder() + .method("POST") + .uri("/v1/chat/completions") + .header("authorization", format!("Bearer {}", AUTH_TOKEN)) + .header("content-type", "application/json") + .body(Body::from(body)) .unwrap(); + let resp = app.oneshot(req).await.unwrap(); assert_eq!(resp.status(), 413); }