# HTTP结果模型 **本文引用的文件** - [http_result.rs](file://crates/shared_types/src/model/http_result.rs) - [app_error.rs](file://crates/shared_types/src/model/app_error.rs) - [lib.rs](file://crates/shared_types/src/lib.rs) - [agent_status_handler.rs(rcoder)](file://crates/rcoder/src/handler/agent_status_handler.rs) - [router.rs(rcoder)](file://crates/rcoder/src/router.rs) - [agent_status_handler.rs(agent_runner)](file://crates/agent_runner/src/handler/agent_status_handler.rs) - [router.rs(agent_runner)](file://crates/agent_runner/src/router.rs) - [chat_response.rs](file://crates/shared_types/src/model/chat_response.rs) - [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考量](#性能考量) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件围绕HTTP结果模型展开,重点说明统一响应格式的设计理念、成功与失败路径的处理逻辑,并结合Axum处理器的返回类型使用,系统性地介绍HttpResult泛型结果类型与AppError错误体系。文档同时梳理错误码与触发条件、错误上下文信息收集机制、序列化输出示例以及客户端错误处理建议,帮助开发者在不同服务中一致地构建标准化API响应。 ## 项目结构 - 共享类型位于 crates/shared_types,其中定义了HttpResult与AppError等跨服务通用模型。 - rcoder与agent_runner两个服务各自实现了Axum路由与处理器,广泛采用HttpResult作为成功响应,AppError作为错误响应。 - 通过lib.rs统一导出共享类型,便于服务间复用。 ```mermaid graph TB subgraph "共享类型" SR["shared_types/lib.rs
统一导出"] HR["model/http_result.rs
HttpResult"] AE["model/app_error.rs
AppError 错误体系"] end subgraph "rcoder 服务" RR["rcoder/router.rs
路由注册"] RH["rcoder/handler/agent_status_handler.rs
处理器示例"] end subgraph "agent_runner 服务" AR["agent_runner/router.rs
路由注册"] AH["agent_runner/handler/agent_status_handler.rs
处理器示例"] end SR --> HR SR --> AE RR --> RH AR --> AH RH --> HR AH --> HR RH --> AE AH --> AE ``` 图表来源 - [lib.rs](file://crates/shared_types/src/lib.rs#L15-L53) - [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L24-L103) - [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L65) - [router.rs(rcoder)](file://crates/rcoder/src/router.rs#L52-L84) - [agent_status_handler.rs(rcoder)](file://crates/rcoder/src/handler/agent_status_handler.rs#L72-L132) - [router.rs(agent_runner)](file://crates/agent_runner/src/router.rs#L41-L70) - [agent_status_handler.rs(agent_runner)](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122) 章节来源 - [lib.rs](file://crates/shared_types/src/lib.rs#L15-L53) - [router.rs(rcoder)](file://crates/rcoder/src/router.rs#L52-L84) - [router.rs(agent_runner)](file://crates/agent_runner/src/router.rs#L41-L70) ## 核心组件 - HttpResult:统一的成功/失败响应载体,包含业务字段code、message、data、tid以及运行时计算的success布尔值。成功路径通过success(data)构造,失败路径通过error(code, message)或internal_error(message)构造。序列化时自动注入success字段,Axum IntoResponse实现负责HTTP状态码与Content-Type设置。 - AppError:统一的错误类型,封装anyhow、IO与通用错误,提供generic、internal_server_error、validation_error等便捷构造方法。其IntoResponse实现将错误标准化为包含error.code与error.message的对象,状态码固定为500。 章节来源 - [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L24-L103) - [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L65) ## 架构总览 下图展示了Axum处理器与统一响应模型之间的交互关系,以及错误路径与成功路径的分流。 ```mermaid sequenceDiagram participant C as "客户端" participant R as "Axum 路由" participant H as "处理器" participant S as "业务逻辑" participant OK as "HttpResult" participant ERR as "AppError" C->>R : "HTTP 请求" R->>H : "调用处理器" H->>S : "执行业务逻辑" alt "成功" S-->>H : "返回数据" H->>OK : "构造 HttpResult : : success(data)" OK-->>R : "IntoResponse" R-->>C : "200 OK + JSON" else "失败" S-->>H : "返回错误" H->>ERR : "构造 AppError 或返回错误" ERR-->>R : "IntoResponse" R-->>C : "500 Internal Server Error + JSON" end ``` 图表来源 - [agent_status_handler.rs(rcoder)](file://crates/rcoder/src/handler/agent_status_handler.rs#L72-L132) - [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L77-L103) - [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L33-L57) ## 详细组件分析 ### HttpResult 泛型结果类型 - 设计理念 - 统一响应格式:所有API响应均包含code、message、data、tid与success字段,便于前端统一解析与展示。 - 成功路径:success(data)构造,code默认“0000”,success=true。 - 失败路径:error(code, message)构造,success=false;internal_error(message)为内部错误的快捷方式。 - 上下文追踪:自动从OpenTelemetry上下文提取trace_id,若无则置空,便于日志与链路追踪。 - 序列化策略:自定义Serialize实现,显式写出5个字段,其中success根据code是否为“0000”动态计算。 - 响应适配:实现IntoResponse,优先返回JSON,序列化失败时降级为500与纯文本。 - 关键行为与复杂度 - 构造函数O(1),序列化O(n)(n为data序列化开销),IntoResponse序列化O(1)+序列化开销。 - trace_id提取依赖当前span上下文,若无效则返回None,不影响响应正确性。 - 使用建议 - 成功场景:优先使用success(data)返回结构化数据。 - 失败场景:明确错误码与message,避免使用internal_error除非无法确定具体原因。 - 数据为空:data字段可为None,但需保证业务语义清晰。 章节来源 - [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L24-L103) ### AppError 错误体系 - 设计理念 - 统一错误抽象:通过枚举封装常见错误来源,便于集中处理与上报。 - 易于扩展:支持From实现,如tokio mpsc SendError的转换,便于在异步通道中传播错误。 - 标准化输出:IntoResponse固定返回500状态码与包含error.code与error.message的对象,便于前端统一处理。 - 错误分类与构造 - AnyhowError:包装底层异常,便于上抛。 - IoError:包装IO错误。 - Generic:通用错误,支持validation_error与internal_server_error等便捷方法。 - 使用建议 - 业务层尽量将错误转换为明确的错误码与message,必要时使用AppError::Generic承载。 - 对于可恢复的业务错误,优先返回HttpResult::error(...)而非抛出AppError,以便客户端区分业务错误与系统错误。 章节来源 - [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L65) ### Axum处理器中的返回类型使用 - 返回类型约定 - 成功:Result, AppError>,处理器返回Ok(HttpResult::success(...))或Ok(HttpResult::error(...))。 - 失败:Result, AppError>,处理器返回Err(AppError::...)或Ok(HttpResult::error(...))。 - 示例:rcoder与agent_runner的agent_status处理器均采用该模式,先做参数校验,再构造AgentStatusResponse并返回HttpResult.success(...),或在参数非法时返回HttpResult.error(...)。 ```mermaid flowchart TD Start(["进入处理器"]) --> Validate["校验输入参数"] Validate --> Valid{"参数有效?"} Valid --> |否| BuildErr["构造 HttpResult::error(code, message)"] BuildErr --> ReturnErr["返回 Ok(HttpResult::error)"] Valid --> |是| DoBiz["执行业务逻辑"] DoBiz --> BizOK{"业务成功?"} BizOK --> |否| BuildBizErr["构造 HttpResult::error(code, message)"] BuildBizErr --> ReturnBizErr["返回 Ok(HttpResult::error)"] BizOK --> |是| BuildData["构造响应数据"] BuildData --> ReturnOk["返回 Ok(HttpResult::success(data))"] ``` 图表来源 - [agent_status_handler.rs(rcoder)](file://crates/rcoder/src/handler/agent_status_handler.rs#L72-L132) - [agent_status_handler.rs(agent_runner)](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122) 章节来源 - [agent_status_handler.rs(rcoder)](file://crates/rcoder/src/handler/agent_status_handler.rs#L72-L132) - [agent_status_handler.rs(agent_runner)](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122) ### 错误码与触发条件 - 内置错误码 - “0000”:成功。 - “5000”:内部错误(internal_error(message)构造)。 - 业务错误码示例 - “INVALID_PARAMS”:参数校验失败(例如agent_status处理器对project_id为空的处理)。 - “INVALID_SESSION”:会话无效(OpenAPI示例中出现)。 - “SESSION_NOT_FOUND”:会话不存在(OpenAPI示例中出现)。 - 触发条件 - 参数校验失败:处理器在进入业务逻辑前进行参数校验,不符合要求时返回HttpResult::error(...)。 - 业务状态异常:如Agent不存在、会话不存在等,返回相应错误码与message。 - 系统异常:无法预期的错误,使用AppError或HttpResult::internal_error(...)。 章节来源 - [agent_status_handler.rs(rcoder)](file://crates/rcoder/src/handler/agent_status_handler.rs#L72-L132) - [agent_status_handler.rs(agent_runner)](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122) - [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L36-L58) ### 错误上下文信息收集机制 - trace_id采集 - HttpResult在构造时与IntoResponse阶段均可从OpenTelemetry上下文提取trace_id,若当前span无效则置空。 - 该机制确保每个响应具备可追踪的链路标识,便于日志聚合与问题定位。 - 请求ID(request_id) - 在聊天响应等结构中提供request_id字段,用于标识与追踪请求,便于跨服务关联。 - 会话消息中的错误字段 - 会话通知结构中包含错误信息字段,便于在SSE流中传递错误详情。 章节来源 - [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L8-L22) - [chat_response.rs](file://crates/shared_types/src/model/chat_response.rs#L1-L18) - [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L71-L97) ### 序列化输出示例 - 成功响应(示例结构) - 字段:code、message、data、tid、success - data为对象或数组时,success为true;data为null时,success仍为true - 失败响应(示例结构) - 字段:code、message、data为null、tid、success为false - 或AppError的标准化错误对象(error.code与error.message) 章节来源 - [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L61-L74) - [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L33-L57) ### 客户端错误处理建议 - 成功与失败路径区分 - 优先依据success字段判断整体成功与否;若为false,读取error.code与error.message进行分支处理。 - 错误码映射 - 将“0000”视为成功;“5000”视为内部错误,提示用户稍后重试或上报工单。 - “INVALID_PARAMS”、“INVALID_SESSION”、“SESSION_NOT_FOUND”等业务错误码用于提示用户修正输入或重新发起请求。 - 上下文追踪 - 记录并回传tid,便于服务端定位问题;在客户端日志中附带request_id,便于跨服务关联。 - 降级与重试 - 对瞬时性错误(如网络抖动)建议客户端进行指数退避重试;对参数类错误直接提示用户修正。 ## 依赖关系分析 - 组件耦合 - HttpResult与AppError均为共享类型,rcoder与agent_runner通过lib.rs统一导出使用,降低重复实现与耦合。 - 处理器依赖共享类型,路由层仅负责注册与文档生成,职责清晰。 - 外部依赖 - OpenTelemetry与tracing用于trace_id采集与日志追踪。 - serde、utoipa用于序列化与OpenAPI文档生成。 - axum用于HTTP响应适配与IntoResponse实现。 ```mermaid graph LR HR["HttpResult"] --> AX["axum::response::IntoResponse"] HR --> OT["opentelemetry/tracing"] HR --> SD["serde"] AE["AppError"] --> AX AE --> TH["thiserror"] RC["rcoder/handler/*"] --> HR RC --> AE AR["agent_runner/handler/*"] --> HR AR --> AE ``` 图表来源 - [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L1-L103) - [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L65) - [lib.rs](file://crates/shared_types/src/lib.rs#L15-L53) 章节来源 - [lib.rs](file://crates/shared_types/src/lib.rs#L15-L53) ## 性能考量 - 序列化成本 - HttpResult的序列化为结构体序列化,主要开销取决于data的大小;建议在成功路径仅返回必要字段,避免冗余数据。 - IntoResponse路径 - 成功路径返回200+JSON,失败路径返回500+JSON;序列化失败时降级为500+纯文本,避免中间件异常。 - trace_id采集 - trace_id提取依赖当前span上下文,若无上下文则跳过,不会引入额外开销。 ## 故障排查指南 - 常见问题 - 响应未携带success字段:确认使用HttpResult而非自定义结构体。 - 错误响应格式不一致:统一使用AppError或HttpResult::error(...),避免混合返回。 - trace_id缺失:检查OpenTelemetry中间件是否正确注入span上下文。 - 定位步骤 - 根据tid在日志系统中检索对应链路。 - 结合request_id在聊天/会话相关接口中定位具体请求。 - 对业务错误码进行聚合统计,识别高频错误与潜在输入问题。 ## 结论 通过HttpResult与AppError的组合,系统实现了统一、可观测、易维护的API响应模型。成功与失败路径清晰分离,错误码与上下文信息完整,配合Axum的IntoResponse实现,能够稳定地输出标准化响应。建议在所有新接口中遵循该模式,以提升客户端体验与运维效率。 ## 附录 - 统一导出入口 - shared_types::lib.rs统一导出HttpResult与AppError,便于服务间复用。 - OpenAPI示例 - rcoder与agent_runner的OpenAPI文档中对HttpResult进行了标注与示例展示,便于客户端理解响应结构。 章节来源 - [lib.rs](file://crates/shared_types/src/lib.rs#L15-L53) - [router.rs(rcoder)](file://crates/rcoder/src/router.rs#L86-L151) - [router.rs(agent_runner)](file://crates/agent_runner/src/router.rs#L72-L128)