在设计 REST 接口的返回码时,需要遵循清晰、一致、可扩展的原则,确保客户端能快速理解接口状态并处理业务逻辑。以下是规划和设计返回码的关键步骤和最佳实践:
一、HTTP 状态码规范(标准返回码)
优先使用标准的 HTTP 状态码,明确表达请求的通用结果(如成功、客户端错误、服务端错误)。以下是常见分类:
1. 2xx 成功
-
200 OK
:请求成功,返回预期数据。 -
201 Created
:资源创建成功(如 POST 请求)。 -
204 No Content
:请求成功,但无返回内容(如 DELETE 请求)。
2. 3xx 重定向
-
301 Moved Permanently
:资源永久迁移。 -
307 Temporary Redirect
:临时重定向。
3. 4xx 客户端错误
-
400 Bad Request
:请求参数错误(如格式错误、必填字段缺失)。 -
401 Unauthorized
:未认证(如缺少 Token)。 -
403 Forbidden
:无权限访问资源。 -
404 Not Found
:资源不存在。 -
409 Conflict
:请求冲突(如重复创建唯一资源)。 -
429 Too Many Requests
:请求频率超限。
4. 5xx 服务端错误
-
500 Internal Server Error
:未知服务端错误。 -
503 Service Unavailable
:服务暂时不可用(如维护中)。
二、自定义业务错误码(细化业务场景)
在标准 HTTP 状态码的基础上,定义业务级别的错误码(如 code
字段),提供更具体的错误信息。
设计原则:
-
唯一性:每个错误码唯一标识一个错误场景。
-
可读性:错误码命名清晰(如
INVALID_PARAM
)。 -
分层设计:按模块或功能划分错误码(如用户模块
USER_XXX
)。 -
兼容性:错误码需预留扩展空间。
错误码格式示例
{
"code": "USER_INVALID_EMAIL", // 业务错误码
"message": "邮箱格式不正确", // 用户友好提示
"detail": "邮箱必须包含 '@' 符号", // 开发者调试信息(可选)
"request_id": "xxx-xxx" // 请求唯一标识(用于日志追踪)
}
三、常见业务场景返回码设计
1. 参数校验错误
-
400 Bad Request
+ 业务码:-
INVALID_PARAM
:参数格式错误。 -
MISSING_PARAM
:缺少必填参数。 -
PARAM_TYPE_ERROR
:参数类型错误。
-
2. 认证与权限
-
401 Unauthorized
+ 业务码:-
AUTH_TOKEN_EXPIRED
:Token 过期。 -
AUTH_TOKEN_INVALID
:Token 无效。
-
-
403 Forbidden
+ 业务码:-
PERMISSION_DENIED
:无操作权限。 -
ACCOUNT_DISABLED
:账号被禁用。
-
3. 资源操作
-
404 Not Found
+ 业务码:-
RESOURCE_NOT_FOUND
:资源不存在。
-
-
409 Conflict
+ 业务码:-
RESOURCE_ALREADY_EXISTS
:资源已存在。 -
DATA_CONFLICT
:数据冲突(如版本号不一致)。
-
4. 业务逻辑错误
-
400 Bad Request
+ 业务码:-
INVALID_OPERATION
:非法操作(如重复提交)。 -
BUSINESS_RULE_VIOLATION
:违反业务规则(如库存不足)。
-
-
429 Too Many Requests
+ 业务码:-
RATE_LIMIT_EXCEEDED
:请求频率超限。
-
四、错误响应结构示例
{
"code": "USER_INVALID_EMAIL",
"message": "邮箱格式不正确",
"detail": "邮箱必须符合标准格式(如 user@example.com)",
"path": "/api/v1/users",
"timestamp": "2023-10-01T12:34:56Z"
}
五、最佳实践
-
一致性:全接口统一错误码命名和响应结构。
-
文档化:提供完整的错误码列表和说明(如 Swagger 文档)。
-
日志记录:服务端记录错误详情(如堆栈跟踪),但响应中避免暴露敏感信息。
-
国际化:
message
字段支持多语言(通过Accept-Language
头动态返回)。 -
版本管理:通过 URL 或 Header 区分 API 版本,错误码需兼容历史版本。
六、错误码扩展性设计
-
模块前缀:通过前缀区分模块(如
PAYMENT_XXX
、ORDER_XXX
)。 -
层级划分:主错误码 + 子错误码(如
PAYMENT_INVALID_CARD_001
表示信用卡类型错误)。
通过以上设计,可以让接口的返回码具备高可读性、易维护性和扩展性,同时降低前后端协作成本。