写API接口返回状态码的问题

一般对于接口返回状态码表示不同的结果,比如登陆,有些人会写很多个状态码,如:101,102,103,而有些人只写一个,如:status为0或者1,具体例子:
只用status一个状态码:

// 只要登陆成功,status为1,否则都为0,具体信息放在msg里面
// 成功
{
    status: 1,
    msg: '登陆成功'
}
// 用户名不存在
{
    status: 0,
    msg: '用户名不存在'
}
// 密码错误
{
    status: 0,
    msg: '密码错误'
}

用多个状态码的情况可能如下:

// 成功
{
    code: 200,
    msg: '登陆成功'
}
// 用户名不存在
{
    code: 201,
    msg: '用户名不存在'
}
// 密码错误
{
    code: 202,
    msg: '密码错误'
}

显然第二种会更麻烦,虽然更具体。大家一般都会第二种的吧,第一种的话,会有什么不合适的地方的呢?想看看大家的想法

阅读 14.2k
11 个回答

我的设计方案是:

code: 状态码
summary: 说明
data: 数据
key: 参数加密
timestamp: 时间戳
nonce: 非重复随机值

说明:

  • code:状态码,使用字符串

    • 数字容易重复,并且不容易记住,调试的时候经常需要翻文档,后来改成字符串,比如:failure_password_or_account_error,这种具有自说明性的状态码,并且不容易重复
    • 成功的时候统一success。其他状态码全局唯一但是各个接口可能会出现相同状态码。
    • 如果有业务状态不一致的地方比如do_something_1do_something2等。
    • 还有一些需要全局捕捉的错误码,比如login_status_timeout,登录过期......
  • summary:说明,是对状态码的说明,一般是中文,

    • 便于调试,
    • 也可以作为文案,让前端直接显示,比如failure_password_or_account_error,前端不需要捕捉这个错误,而直接提示summary,此时sumamry的内容是账户或者密码错误,这样前端就不需要捕捉每个状态码,只需要捕捉特定的的就好了。
    • 还能防止新的错误码出现前端没有捕捉,补充空白文案。比如后端突然、或者前端没有捕捉一个错误码error_yo_yo:异地登录,请重新登录,这时候前端暂时不捕捉也没事,毕竟默认就把summary提示出来了,所以用户就会看到异地登录,请重新登录的提示,虽然跳到登录页面更好,但是暂时也不影响用户操作。
  • data:这是真正的数据,需要的时候就返回
  • key:对data的加密,用来校验参数是否被篡改
  • timestamp:时间戳,可用来加密data入参,同时给后端校验
  • nonce:无意义随机字符串,配合timestamp防重放攻击

说明:

上面的流程直接封装成网络层,配合模型层,上层的业务几乎感觉不到这里的繁杂的东西,对上层来说,该捕捉状态码的时候,直接捕捉,不需要捕捉的时候,甚至都不用理会。将细节屏蔽扩展能力扩大才是最优的

使用经验:

这一套使用了大概2年,也经过好几次改版和迭代,横跨了十多个项目,涉及原生安卓iosjs 等,虽然上面有很多细节没有说的很清晰,但是也差不多了。

第二种。
第一种只有0和1的话,太单一。遇上需要特殊处理的case就很麻烦。
比如说如果需求是'用户名不存在'要自动跳转到注册页面,而'密码错误'只是提示就好,这时候第一种就会显得不够了

我赞成方案二

msg可以认为是一种服务端下发的提示文案。

code认为是一个固定的错误id

第一种的话,成了msg+code共同表示一个错误了

对于前段来说第一种比较方便

我是 成功返回0 提示类的 错误返回1 需特殊处理的case返回其他数字

第一种。
虽然第二种更具体,但是实际上并不一定有啥用,对于用户来说,密码不正确或者用户名不存在反正都是错误,前台要那code并没啥用。
不过如果不是前后端分离情况的话,光code和msg是不够用的,最好加一个url字段,用于前台是否需要跳转。

第三种方式,比如errcode值为10000的时候表示成功,其他情况下比如111021的含义会拆分成“1”,“11”,“021”这样去解读。第一个1表示模块如index、wap、api等模块。第二个11表示模块下的方法,最后一个021表示错误的行数。方便问题排查吧。
个人觉得习惯哪种用哪种,没有啥是必须遵守的。

其实这个还是看团队吧,比如最近写的一个Api,我前期定义错误返回码:

$map = [
    -1001 => '用户名不存在',
    -1002 => '密码错误',
    -1003 => '验证码错误'
];

采用定义一个这样map错误码,1 001,1代表模块,001代表错误码。只是前台那里只要你不是返回200(约定成功返回200),其他一律都认定错误返回码。其实通过200(成功),-200(不成功)这种简单的也可以,因为你请求出现的异常错误,肯定是在同一个模块下的报错,所以排查起来也不是很麻烦。

一些特殊的状态码,肯定是要约定好的。如token过期需要重新登陆

-100 => '请重新登陆'

这样。

响应体组成

字段 含义
code 服务端处理业务后的返回代码,其中包含公共响应代码和当前业务特有代码
组成右 http_code+3位数字,成功除外,成功使用200表示,其他的,如
客户端请求权限错误 401001
msg 服务端处理后返回给客户端的提示性文字,当然,客户端不应该直接使用此
提示,而是根据code自定义提示语给用户
data 处理业务逻辑后需要返回的数据,必须为一个对象,而非任何标量值
session 这里的session并不是传统http中的session,而是单次会话的标识符,因为在
客户端调用API的过程中,难免会遇到数据问题,导致不好调试,所以应该将
所有的请求记录放进去日志,然后当客户端出现问题时根据请求的session来
定位是哪一个会话,然后使用postman对请求进行重放调试,除了请求日志,
还应该保存请求日志

公共响应代码

除了业务响应代码,应该还有一些公共响应代码

code 示例
200 请求成功
401001 用户身份失效
400001 请求参数错误
404001 服务没有数据

....

其实合适的就是好的方案。比如有的项目接口都很简单,不过就是普通的增删改查,没啥复杂逻辑,错误定位简单。前端也不需要告诉用户后端的具体错误内容,就简单提示操作出错、失败就可以了。那么状态码可以很简单,甚至0,1就够了。 大型的项目就需要一开始把各个模块的状态码定义好,方便定位捕捉各种错误类型。

更倾向于第二种,并且也建议直接用第二种,也是系统优化茁壮的必然选择。
楼上有人说对前端方便与否的,其实都一样,正确状态码就一个 0,1,200 视自己习惯而定,其他都是错误码,像我习惯0是success,其他都是异常,而对前端来说无非是判断是0还是1与判断是0还是非0的区别 实在想不通这算什么麻烦?
采用第二种方案后端给出详细错误code能使错误信息更精准,嫌麻烦无意义的直接当成0和1用统一错误提示即可,也就是说第二种方案是可以向第一种无缝兼容的
但一但决定采用第一种方案,后端只给你一种错误code,你以后后端想改第二种的话那代码量就可观了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题