diff --git a/rust/src/server/src/routes.rs b/rust/src/server/src/routes.rs index ce94e2ecab..1f7dd03809 100644 --- a/rust/src/server/src/routes.rs +++ b/rust/src/server/src/routes.rs @@ -17,6 +17,7 @@ mod world_size; use std::sync::Arc; use axum::Router; +use axum::extract::DefaultBodyLimit; use axum::middleware::{from_fn, from_fn_with_state}; use axum::routing::{get, post}; use tower_http::trace::TraceLayer; @@ -24,6 +25,8 @@ use tower_http::trace::TraceLayer; use crate::middleware; use crate::state::AppState; +const DEFAULT_JSON_BODY_LIMIT_BYTES: usize = 32 * 1024 * 1024; + fn server_dev_mode_enabled() -> bool { std::env::var("VLLM_SERVER_DEV_MODE") .ok() @@ -108,6 +111,7 @@ fn build_router_with_options( let enable_api_key_auth = state.has_api_keys(); let mut router = router .with_state(state.clone()) + .layer(DefaultBodyLimit::max(DEFAULT_JSON_BODY_LIMIT_BYTES)) .layer(middleware::request_runtime_layer(state.clone())) .layer(from_fn_with_state( state.clone(), diff --git a/rust/src/server/src/routes/tests.rs b/rust/src/server/src/routes/tests.rs index 88c6835139..0c3450caf1 100644 --- a/rust/src/server/src/routes/tests.rs +++ b/rust/src/server/src/routes/tests.rs @@ -3510,6 +3510,46 @@ async fn non_stream_chat_completions_still_succeed() { engine_task.await.expect("mock engine task"); } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +#[serial] +async fn chat_completions_accepts_request_body_larger_than_axum_default() { + let (chat, engine_task) = test_chat_with_engine_outputs( + b"engine-openai-chat-large-body", + default_stream_output_specs(), + ) + .await; + let mut app = build_router(Arc::new(AppState::new( + vec!["Qwen/Qwen1.5-0.5B-Chat".to_string()], + chat, + ))); + + let large_template_arg = "a".repeat(2 * 1024 * 1024); + let response = app + .call( + Request::builder() + .method("POST") + .uri("/v1/chat/completions") + .header("content-type", "application/json") + .body(Body::from( + json!({ + "model": "Qwen/Qwen1.5-0.5B-Chat", + "stream": false, + "messages": [{"role": "user", "content": "hello"}], + "chat_template_kwargs": {"large": large_template_arg} + }) + .to_string(), + )) + .expect("build request"), + ) + .await + .expect("call app"); + + let status = response.status(); + let body = to_bytes(response.into_body(), usize::MAX).await.expect("read body"); + assert_eq!(status, StatusCode::OK, "{}", String::from_utf8_lossy(&body)); + engine_task.await.expect("mock engine task"); +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[serial] async fn non_stream_completions_still_succeed() {