补齐错误 envelope 的请求上下文并扩展游戏分发审核取证
Project CI / AI game creator shell Rust crates (push) Successful in 1m30s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m59s
Project CI / AI game creator shell Rust lane 2/2 (push) Failing after 5m26s
Project CI / Backend tests (push) Successful in 4m13s
Project CI / Frontend tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
Project CI / AI game creator shell Rust lane 1/2 (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / AI game creator shell Rust crates (push) Successful in 1m30s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m59s
Project CI / AI game creator shell Rust lane 2/2 (push) Failing after 5m26s
Project CI / Backend tests (push) Successful in 4m13s
Project CI / Frontend tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
Project CI / AI game creator shell Rust lane 1/2 (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
- api-server 的错误响应改用 attach_request_context 建立的 CURRENT_REQUEST_CONTEXT(tokio task_local),错误 envelope 与成功 envelope 一样带 meta.requestId / meta.operation,脱离请求任务时退回原形状 - 越权隔离脚本新增成功/失败 envelope 断言:修复前错误响应 requestId 为空让断言变红,修复后 23 项 PASS - 媒体链路脚本扩展审核治理段:普通作者不能提交审核动作、更新待审与被拒都不改变在线旧版 URL 与可玩内容、审核结论可在后台追溯,44 项 PASS - 游戏分发里程碑阶段 A 第 6 条、阶段 B 第 1/2 条改为已勾选并写入取证,阶段 B 其余条目列出具体缺口 - decision-log 补记错误 envelope 同一份 meta 与「按可消费取证」两条口径
This commit is contained in:
@@ -6,7 +6,10 @@ use axum::{
|
||||
use serde_json::Value;
|
||||
use shared_contracts::api::ApiErrorPayload;
|
||||
|
||||
use crate::{api_response::json_error_body, request_context::RequestContext};
|
||||
use crate::{
|
||||
api_response::json_error_body,
|
||||
request_context::{CURRENT_REQUEST_CONTEXT, RequestContext},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AppError {
|
||||
@@ -112,7 +115,14 @@ impl AppError {
|
||||
|
||||
impl IntoResponse for AppError {
|
||||
fn into_response(self) -> Response {
|
||||
self.into_response_with_context(None)
|
||||
// 绝大多数 handler 错误是在 `attach_request_context` 的任务里转成响应的:
|
||||
// 这里带上同一份 requestId / operation,错误 envelope 才与成功 envelope 一致;
|
||||
// 脱离请求任务(测试、后台任务)时退回无上下文的形状。
|
||||
if CURRENT_REQUEST_CONTEXT.try_with(|_| ()).is_ok() {
|
||||
CURRENT_REQUEST_CONTEXT.with(|context| self.into_response_with_context(Some(context)))
|
||||
} else {
|
||||
self.into_response_with_context(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,12 @@ use uuid::Uuid;
|
||||
|
||||
pub use shared_contracts::api::X_REQUEST_ID_HEADER;
|
||||
|
||||
tokio::task_local! {
|
||||
/// 当前请求的上下文:`AppError::into_response` 这类拿不到 extensions 的转换也要按同一份
|
||||
/// meta 口径给出 requestId / operation,错误 envelope 与成功 envelope 才不会各写一套。
|
||||
pub static CURRENT_REQUEST_CONTEXT: RequestContext;
|
||||
}
|
||||
|
||||
// 当前阶段先把请求级元信息统一挂到 extensions,后续响应头、envelope 与错误处理中间件继续复用。
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RequestContext {
|
||||
@@ -80,12 +86,14 @@ pub async fn attach_request_context(mut request: Request, next: Next) -> Respons
|
||||
.unwrap_or_else(|| Uuid::new_v4().to_string());
|
||||
let operation = format!("{} {}", request.method(), request.uri());
|
||||
|
||||
request.extensions_mut().insert(RequestContext::new(
|
||||
let context = RequestContext::new(
|
||||
request_id.clone(),
|
||||
operation,
|
||||
Duration::ZERO,
|
||||
wants_envelope,
|
||||
));
|
||||
);
|
||||
let context_for_scope = context.clone();
|
||||
request.extensions_mut().insert(context);
|
||||
|
||||
// 统一把 request_id 写回请求头,方便后续 tracing、响应头与 envelope 层读取同一来源。
|
||||
if let Ok(header_value) = HeaderValue::from_str(&request_id) {
|
||||
@@ -94,7 +102,9 @@ pub async fn attach_request_context(mut request: Request, next: Next) -> Respons
|
||||
.insert(HeaderName::from_static(X_REQUEST_ID_HEADER), header_value);
|
||||
}
|
||||
|
||||
next.run(request).await
|
||||
CURRENT_REQUEST_CONTEXT
|
||||
.scope(context_for_scope, async move { next.run(request).await })
|
||||
.await
|
||||
}
|
||||
|
||||
pub fn resolve_request_id<B>(request: &HttpRequest<B>) -> Option<String> {
|
||||
|
||||
Reference in New Issue
Block a user