2. API设计治理基础:RESTful与GraphQL设计原则,错误码规范,响应体结构标准化
在错误处理移植适配之前,必须建立统一的API设计治理基线。RESTful与GraphQL作为当前最主流的两种API范式,其设计原则、错误码规范与响应体结构直接影响错误信息的传递效率与可移植性。本章将系统梳理这两大范式的核心治理要素,为后续事务边界中的错误处理适配奠定基础。
2.1 RESTful设计原则与错误处理基线
RESTful API以资源为中心,通过HTTP动词表达操作意图。其错误处理的核心原则是:利用HTTP状态码表达语义,利用响应体传递细节。
2.1.1 HTTP状态码分层使用规范
| 类别 | 状态码 | 语义 | 典型场景 |
|---|---|---|---|
| 成功 | 200 / 201 / 204 | 请求已处理 | GET返回200,POST创建返回201,DELETE成功返回204 |
| 客户端错误 | 400 / 401 / 403 / 404 / 409 / 422 | 请求无效或无法处理 | 参数校验失败(400),资源不存在(404),冲突(409),校验语义错误(422) |
| 服务端错误 | 500 / 502 / 503 | 服务端异常 | 内部错误(500),网关超时(502),服务不可用(503) |
治理要点:禁止将业务逻辑错误映射为200状态码。所有业务异常必须使用4xx或5xx状态码,确保客户端能够通过状态码快速判断请求结果类别。
2.1.2 RESTful响应体标准化结构
标准化的响应体结构是错误处理可移植的前提。推荐采用信封模式(Envelope Pattern),将数据与元数据分离:
// 成功响应
{
"code": 0,
"message": "success",
"data": {
"id": "usr_12345",
"name": "张三",
"email": "zhangsan@example.com"
},
"requestId": "req_abc123",
"timestamp": 1712563200000
}
// 错误响应
{
"code": 40001,
"message": "参数校验失败",
"data": null,
"errors": [
{
"field": "email",
"rule": "email_format",
"message": "邮箱格式不正确"
},
{
"field": "age",
"rule": "range",
"message": "年龄必须在18-120之间"
}
],
"requestId": "req_def456",
"timestamp": 1712563201000
}
关键字段说明:
- code:业务错误码,0表示成功,非0表示具体错误类型
- message:人类可读的错误概要
- errors:错误详情数组,支持多字段校验错误聚合
- requestId:请求追踪标识,用于日志关联与问题定位
2.2 GraphQL设计原则与错误处理差异
GraphQL采用单一端点、按需查询的模式,其错误处理机制与RESTful存在显著差异。GraphQL规范要求:无论请求是否部分失败,始终返回200状态码,错误信息嵌入响应体的errors数组中。
2.2.1 GraphQL响应体结构
{
"data": {
"user": {
"id": "usr_12345",
"name": "张三",
"orders": null
}
},
"errors": [
{
"message": "无法获取用户订单列表",
"locations": [{"line": 6, "column": 5}],
"path": ["user", "orders"],
"extensions": {
"code": "ORDER_FETCH_ERROR",
"service": "order-service",
"timestamp": "2024-04-08T10:00:01Z"
}
}
]
}
| 字段 | 说明 | 治理要求 |
|---|---|---|
message |
错误描述(必填) | 必须清晰、无歧义,面向开发者 |
locations |
错误在查询中的位置 | 自动生成,用于调试 |
path |
错误字段的路径 | 帮助客户端定位失败字段 |
extensions |
扩展信息(推荐) | 必须包含业务错误码、服务标识、时间戳 |
移植适配注意:GraphQL的200+errors模式与RESTful的4xx/5xx模式在错误传递路径上完全不同。在事务边界中,必须设计统一的错误码映射层,将GraphQL的
extensions.code与RESTful的code字段对齐,避免下游消费者因范式差异而解析失败。
2.3 统一错误码规范设计
错误码是跨范式移植适配的核心桥梁。无论采用RESTful还是GraphQL,错误码必须遵循统一的编码规则,确保在事务边界中能够被正确识别与转换。
2.3.1 错误码分层编码规则
2.3.2 错误类别定义表
| 错误类别码 | 类别名称 | 说明 | HTTP映射 |
|---|---|---|---|
| 01 | 认证错误 | 身份验证失败、Token过期 | 401 |
| 02 | 参数校验错误 | 请求参数格式、范围、必填校验失败 | 400 / 422 |
| 03 | 资源错误 | 资源不存在、资源冲突 | 404 / 409 |
| 04 | 权限错误 | 无操作权限、角色不匹配 | 403 |
| 05 | 业务逻辑错误 | 业务规则违反、状态机异常 | 422 / 409 |
| 06 | 服务端错误 | 内部异常、依赖服务故障 | 500 / 502 / 503 |
2.4 响应体结构标准化对比
在事务边界中,RESTful与GraphQL的响应体结构需要统一抽象。下表展示了两者在关键维度上的对比及适配策略:
| 维度 | RESTful | GraphQL | 适配策略 |
|---|---|---|---|
| 状态码 | HTTP状态码(200/4xx/5xx) | 始终200 | 统一提取业务错误码,忽略HTTP状态码差异 |
| 错误位置 | 响应体顶层errors数组 | 响应体errors数组 | 结构兼容,可直接映射 |
| 字段级错误 | errors[].field + errors[].message | errors[].path + errors[].message | 统一转换为field+path双标识 |
| 扩展信息 | 自定义字段(如requestId) | errors[].extensions | 统一放入extensions命名空间 |
| 部分成功 | 不支持(全成功或全失败) | 支持(data部分为null) | 引入部分成功标记字段 |
2.5 范式适配架构图
在API治理层面,需要构建一个错误处理适配层,将RESTful与GraphQL的错误输出统一为内部标准格式,确保事务边界中的错误处理逻辑与前端范式解耦。
适配层核心职责:
- 错误码映射:将RESTful的HTTP状态码+业务码、GraphQL的extensions.code统一映射为6位标准错误码
- 结构转换:将RESTful的errors[].field与GraphQL的errors[].path统一为field+path双字段
- 元数据注入:统一注入requestId、timestamp、serviceName等追踪字段
- 部分成功处理:对GraphQL的部分成功场景,生成统一的partialSuccess标记
2.6 治理基线检查清单
在进入事务边界错误处理移植适配之前,请确保以下治理基线已落实:
| 检查项 | RESTful要求 | GraphQL要求 | 验收标准 |
|---|---|---|---|
| 状态码使用 | 严格遵循4xx/5xx语义 | 始终返回200 | 无业务错误使用200状态码 |
| 响应体结构 | 信封模式(code+data+errors) | data+errors+extensions | 统一包含code、message、requestId |
| 错误码规范 | 6位数字分层编码 | extensions.code使用6位数字 | 错误码可跨范式映射 |
| 字段级错误 | errors[].field | errors[].path | 适配层统一输出field+path |
| 追踪标识 | requestId | extensions.requestId | 所有响应包含唯一请求ID |
常见治理陷阱:
- 将业务错误(如余额不足)映射为500状态码——应使用422或409
- GraphQL中遗漏extensions字段,导致下游无法获取业务错误码
- 错误码编码不统一,RESTful使用4位码而GraphQL使用字符串码
- 忽略部分成功场景,导致客户端无法区分全成功与部分成功