Files
2026-06-01 13:54:52 +08:00

299 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# HTTP结果模型
<cite>
**本文引用的文件**
- [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.rsrcoder](file://crates/rcoder/src/handler/agent_status_handler.rs)
- [router.rsrcoder](file://crates/rcoder/src/router.rs)
- [agent_status_handler.rsagent_runner](file://crates/agent_runner/src/handler/agent_status_handler.rs)
- [router.rsagent_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)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件围绕HTTP结果模型展开重点说明统一响应格式的设计理念、成功与失败路径的处理逻辑并结合Axum处理器的返回类型使用系统性地介绍HttpResult<T>泛型结果类型与AppError错误体系。文档同时梳理错误码与触发条件、错误上下文信息收集机制、序列化输出示例以及客户端错误处理建议帮助开发者在不同服务中一致地构建标准化API响应。
## 项目结构
- 共享类型位于 crates/shared_types其中定义了HttpResult<T>与AppError等跨服务通用模型。
- rcoder与agent_runner两个服务各自实现了Axum路由与处理器广泛采用HttpResult<T>作为成功响应AppError作为错误响应。
- 通过lib.rs统一导出共享类型便于服务间复用。
```mermaid
graph TB
subgraph "共享类型"
SR["shared_types/lib.rs<br/>统一导出"]
HR["model/http_result.rs<br/>HttpResult<T>"]
AE["model/app_error.rs<br/>AppError 错误体系"]
end
subgraph "rcoder 服务"
RR["rcoder/router.rs<br/>路由注册"]
RH["rcoder/handler/agent_status_handler.rs<br/>处理器示例"]
end
subgraph "agent_runner 服务"
AR["agent_runner/router.rs<br/>路由注册"]
AH["agent_runner/handler/agent_status_handler.rs<br/>处理器示例"]
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.rsrcoder](file://crates/rcoder/src/router.rs#L52-L84)
- [agent_status_handler.rsrcoder](file://crates/rcoder/src/handler/agent_status_handler.rs#L72-L132)
- [router.rsagent_runner](file://crates/agent_runner/src/router.rs#L41-L70)
- [agent_status_handler.rsagent_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.rsrcoder](file://crates/rcoder/src/router.rs#L52-L84)
- [router.rsagent_runner](file://crates/agent_runner/src/router.rs#L41-L70)
## 核心组件
- HttpResult<T>:统一的成功/失败响应载体包含业务字段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<T>"
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.rsrcoder](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<T> 泛型结果类型
- 设计理念
- 统一响应格式所有API响应均包含code、message、data、tid与success字段便于前端统一解析与展示。
- 成功路径success(data)构造code默认“0000”success=true。
- 失败路径error(code, message)构造success=falseinternal_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<HttpResult<T>, AppError>处理器返回Ok(HttpResult::success(...))或Ok(HttpResult::error(...))。
- 失败Result<HttpResult<T>, 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.rsrcoder](file://crates/rcoder/src/handler/agent_status_handler.rs#L72-L132)
- [agent_status_handler.rsagent_runner](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122)
章节来源
- [agent_status_handler.rsrcoder](file://crates/rcoder/src/handler/agent_status_handler.rs#L72-L132)
- [agent_status_handler.rsagent_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.rsrcoder](file://crates/rcoder/src/handler/agent_status_handler.rs#L72-L132)
- [agent_status_handler.rsagent_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<T>在构造时与IntoResponse阶段均可从OpenTelemetry上下文提取trace_id若当前span无效则置空。
- 该机制确保每个响应具备可追踪的链路标识,便于日志聚合与问题定位。
- 请求IDrequest_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为truedata为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<T>与AppError均为共享类型rcoder与agent_runner通过lib.rs统一导出使用降低重复实现与耦合。
- 处理器依赖共享类型,路由层仅负责注册与文档生成,职责清晰。
- 外部依赖
- OpenTelemetry与tracing用于trace_id采集与日志追踪。
- serde、utoipa用于序列化与OpenAPI文档生成。
- axum用于HTTP响应适配与IntoResponse实现。
```mermaid
graph LR
HR["HttpResult<T>"] --> 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<T>的序列化为结构体序列化主要开销取决于data的大小建议在成功路径仅返回必要字段避免冗余数据。
- IntoResponse路径
- 成功路径返回200+JSON失败路径返回500+JSON序列化失败时降级为500+纯文本,避免中间件异常。
- trace_id采集
- trace_id提取依赖当前span上下文若无上下文则跳过不会引入额外开销。
## 故障排查指南
- 常见问题
- 响应未携带success字段确认使用HttpResult<T>而非自定义结构体。
- 错误响应格式不一致统一使用AppError或HttpResult::error(...),避免混合返回。
- trace_id缺失检查OpenTelemetry中间件是否正确注入span上下文。
- 定位步骤
- 根据tid在日志系统中检索对应链路。
- 结合request_id在聊天/会话相关接口中定位具体请求。
- 对业务错误码进行聚合统计,识别高频错误与潜在输入问题。
## 结论
通过HttpResult<T>与AppError的组合系统实现了统一、可观测、易维护的API响应模型。成功与失败路径清晰分离错误码与上下文信息完整配合Axum的IntoResponse实现能够稳定地输出标准化响应。建议在所有新接口中遵循该模式以提升客户端体验与运维效率。
## 附录
- 统一导出入口
- shared_types::lib.rs统一导出HttpResult与AppError便于服务间复用。
- OpenAPI示例
- rcoder与agent_runner的OpenAPI文档中对HttpResult<T>进行了标注与示例展示,便于客户端理解响应结构。
章节来源
- [lib.rs](file://crates/shared_types/src/lib.rs#L15-L53)
- [router.rsrcoder](file://crates/rcoder/src/router.rs#L86-L151)
- [router.rsagent_runner](file://crates/agent_runner/src/router.rs#L72-L128)