build: echo request id response header

This commit is contained in:
2026-04-21 01:30:16 +08:00
parent f7663076a5
commit 0cbda6aa7c
5 changed files with 30 additions and 2 deletions

View File

@@ -102,7 +102,8 @@
交付物:[../server-rs/apps/api-server/src/http_error.rs](../server-rs/apps/api-server/src/http_error.rs)、[../server-rs/apps/api-server/src/error_middleware.rs](../server-rs/apps/api-server/src/error_middleware.rs)、[../server-rs/apps/api-server/src/app.rs](../server-rs/apps/api-server/src/app.rs)
- [x] 接入当前项目兼容的 response envelope
交付物:[../server-rs/apps/api-server/src/api_response.rs](../server-rs/apps/api-server/src/api_response.rs)、[../server-rs/apps/api-server/src/request_context.rs](../server-rs/apps/api-server/src/request_context.rs)、[../server-rs/apps/api-server/src/http_error.rs](../server-rs/apps/api-server/src/http_error.rs)
- [ ] 接入 `x-request-id`
- [x] 接入 `x-request-id`
交付物:[../server-rs/apps/api-server/src/response_headers.rs](../server-rs/apps/api-server/src/response_headers.rs)、[../server-rs/apps/api-server/src/app.rs](../server-rs/apps/api-server/src/app.rs)
- [ ] 接入 `x-api-version`
- [ ] 接入 `x-route-version`
- [ ] 接入 `x-response-time-ms`

View File

@@ -43,7 +43,7 @@
1. 中间件优先读取来访 `x-request-id`,未提供时生成新的 UUID。
2. `request_id` 会统一写入请求 `extensions` 与请求头,供 tracing、错误处理中间件和响应头层复用。
3. 响应回写 `x-request-id` 仍属于后续独立任务,本阶段只完成请求上下文准备
3. 最终响应回写同一个 `x-request-id`,保证调用方、日志链路和后续 envelope `meta.requestId` 可对齐
当前错误处理中间件约定:

View File

@@ -5,6 +5,7 @@ use tracing::{info_span, Level};
use crate::{
error_middleware::normalize_error_response,
request_context::{attach_request_context, resolve_request_id},
response_headers::propagate_request_id_header,
state::AppState,
};
@@ -13,6 +14,8 @@ pub fn build_router(state: AppState) -> Router {
Router::new()
// 错误归一化层放在 tracing 里侧,让 tracing 记录到最终对外返回的状态与错误体形态。
.layer(middleware::from_fn(normalize_error_response))
// 响应头回写放在错误归一化外侧,确保最终写回的是归一化后的最终响应。
.layer(middleware::from_fn(propagate_request_id_header))
// 当前阶段先统一挂接 HTTP tracing后续 request_id、响应头与错误中间件继续在这里扩展。
.layer(
TraceLayer::new_for_http()

View File

@@ -5,6 +5,7 @@ mod error_middleware;
mod http_error;
mod logging;
mod request_context;
mod response_headers;
mod state;
use tokio::net::TcpListener;

View File

@@ -0,0 +1,23 @@
use axum::{
extract::Request,
http::{header::HeaderName, HeaderValue},
middleware::Next,
response::Response,
};
use crate::request_context::{resolve_request_id, X_REQUEST_ID_HEADER};
pub async fn propagate_request_id_header(request: Request, next: Next) -> Response {
let request_id = resolve_request_id(&request);
let mut response = next.run(request).await;
if let Some(request_id) = request_id {
if let Ok(header_value) = HeaderValue::from_str(&request_id) {
response
.headers_mut()
.insert(HeaderName::from_static(X_REQUEST_ID_HEADER), header_value);
}
}
response
}