执行摘要
本 PR 为 Rust 前端正式支持 --enable-request-id-headers 参数,将请求 ID 头功能从未支持列表迁移至正式支持。改动范围涵盖 CLI 参数定义、状态管理、中间件实现、路由层集成及配套测试,与 Python vLLM 的 XRequestIdMiddleware 行为完全对齐。
功能与动机
在 Python vLLM 中,--enable-request-id-headers 允许在每个 HTTP 响应中添加 X-Request-Id 头,便于请求追踪和调试。Rust 前端此前仅将该参数标记为“未支持”,用户无法使用。本 PR 由 Rust 前端维护者 BugenZhao 审阅,旨在补齐这一功能缺口,使 Rust 前端行为与 Python 版本保持一致。
实现拆解
- CLI 参数定义:在
rust/src/cmd/src/cli.rs 的 SharedRuntimeArgs 中添加 enable_request_id_headers 字段(clap 派生,long 为 --enable-request-id-headers),并从 unsupported.rs 中移除对应条目。
- 状态管理:在
rust/src/server/src/state.rs 的 AppState 中新增 enable_request_id_headers: bool 字段,默认 false;提供构建器方法 with_request_id_headers。
- 中间件实现:新建
rust/src/server/src/middleware/request_id.rs,实现 set_request_id_header 函数:从请求头提取 X-Request-Id,若存在则回显,否则生成 uuid4 hex 字符串,并插入响应头。
- 路由层集成:在
rust/src/server/src/routes.rs 的 build_router_with_dev_mode 中,条件性地添加 set_request_id_header 中间件层(仅当 enable_request_id_headers 为 true 时)。
- 模块导出:更新
lib.rs 和 middleware/mod.rs 以导出新模块;在 config.rs 中添加对应配置字段。
- 测试配套:
- CLP 测试(
cli/tests.rs):serve_passes_enable_request_id_headers_into_config 和 frontend_args_json_passes_enable_request_id_headers_into_config。
- 集成测试(
routes/tests.rs):request_id_header_is_absent_by_default、request_id_header_generates_uuid_hex_when_enabled、request_id_header_echoes_incoming_header_when_enabled。
rust/src/server/src/middleware/request_id.rs
新增核心中间件,实现 X-Request-Id 头的设置逻辑。
use axum::extract::Request;
use axum::http::HeaderValue;
use axum::http::header::HeaderName;
use axum::middleware::Next;
use axum::response::Response;
use uuid::Uuid;
const X_REQUEST_ID: HeaderName = HeaderName::from_static("x-request-id");
/// Echo the request's `X-Request-Id` on the response, or generate a fresh
/// `uuid4` hex if the request did not provide one.
///
/// Original Python:
/// `vllm.entrypoints.openai.server_utils.XRequestIdMiddleware`.
pub async fn set_request_id_header(req: Request, next: Next) -> Response {
// 提取请求头中的 X-Request-Id 值
let incoming = req.headers().get(&X_REQUEST_ID).cloned();
let mut response = next.run(req).await;
// 如果请求头中存在则使用,否则生成 uuid4 hex
let value = incoming.unwrap_or_else(|| {
HeaderValue::from_str(&Uuid::new_v4().simple().to_string())
.expect("uuid hex is valid header value")
});
response.headers_mut().insert(X_REQUEST_ID, value);
response
}
rust/src/server/src/state.rs
在 AppState 中添加 enable_request_id_headers 字段和构建器方法,是条件启用中间件的状态基础。
/// Shared router state for the minimal single-model OpenAI server.
pub struct AppState {
/// 所有托管的模型 ID 列表
served_model_names: Vec<String>,
/// 共享的 ChatLlm 实例
pub chat: ChatLlm,
/// 是否记录每个请求的日志
pub enable_log_requests: bool,
/// 是否在每个 HTTP 响应中设置 X-Request-Id 头
pub enable_request_id_headers: bool,
/// 当前正在处理的请求数(用于 /load 端点)
server_load: AtomicU64,
}
impl AppState {
// ...
/// 启用 X-Request-Id 响应头
pub fn with_request_id_headers(mut self, enabled: bool) -> Self {
self.enable_request_id_headers = enabled;
self
}
}
rust/src/server/src/routes.rs
路由层条件添加 set_request_id_header 中间件,是功能生效的入口。
fn build_router_with_dev_mode(state: Arc<AppState>, dev_mode_enabled: bool) -> Router {
// ... 各种路由注册 ...
let enable_request_id_headers = state.enable_request_id_headers;
let mut router = router
.with_state(state.clone())
.layer(from_fn_with_state(state, middleware::track_server_load))
.layer(from_fn(middleware::track_http_metrics))
.layer(TraceLayer::new_for_http());
// 当启用请求 ID 头时,插入 set_request_id_header 中间件
if enable_request_id_headers {
router = router.layer(from_fn(middleware::set_request_id_header));
}
router
}
评论区精华
ricky-chaoju: 认为 visible_alias = "no-enable-request-id-headers" 配合 default_missing_value = "true" 会导致 --no-enable-request-id-headers 反而设置 true 的错误语义。建议要么实现真正的 false 语义,要么删除该别名。
BugenZhao: 解释 Rust 端通过 args-json 接收 Python 解析后的值,negative form 已在 Python 端处理,因此 Rust 端只需保留正向参数,删除 negative form。
cinnamonica02: 采纳建议,删除 negative form 支持及相关测试,并更新 PR。
风险与影响
- 风险:整体风险低。新功能默认关闭,不影响现有行为。中间件逻辑简单(仅插入头),无性能隐患。测试覆盖了 CLI 解析和 HTTP 行为的主要路径。
- 影响:对用户新增一个可选参数,方便请求追踪;对系统无侵入;对团队而言完善了 Rust 前端与 Python 前端的对等性,为后续类似参数迁移提供了参考。
关联脉络
本 PR 是 Rust 前端功能补齐系列的一部分,继续缩小与 Python 前端的参数差距。此前已有多个 Rust 前端特性 PR(如 44126 多模态视频加载、42977 解析器迁移、44267 统一解析器等),本 PR 聚焦于 HTTP 中间件参数,体现了团队对 Rust 前端可用性的持续投入。
参与讨论