API 使用 HTTP 状态码还是全部返回 200

2015-05-16 15:43:29 +08:00
 schemacs

如题,方案一:所有就是只以HTTP状态码来表示状态,200时候返回内容就是数据,最多有个分页(其实分页我都不想放响应内容里,我觉得像github那样放到header更整洁)。

{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": 1,
            ...
        }
    ]
}

只有在抛出Exception异常(即使业务逻辑上有问题,也抛出APIException异常)才返回:

HTTP/1.1 405 Method Not Allowed
Content-Type: application/json

{"status_code": 405, "message": "Method 'DELETE' not allowed."}

方案二:所有接口都返回200(我觉得有点不切实际,比如403,500等,再加上很多客户端http库都会对这些抛异常的),然后响应里包含:

{
    "status_code: 1000
    "message": "xxxxx"
    "result": {
        "id": 1
        ...
    }
}

现在貌似很多客户端开发都希望是方案二,因为这样他们逻辑会简单些(200以外全去捕获异常,200时再看status_code做不同处理),但是作为服务端更倾向于方案一,因为大多框架和各家提供的API都是这么干的,其实也很简单(先看状态码,然后直接根据状态码决定后续动作)。

在两个方案中纠结,来请大家给点建议哈~

以前都是在SO上发帖,第一次在v站发帖,如有没说清楚或者违反社区原则的地方,请大家不吝指出。

28417 次点击
所在节点    程序员
65 条回复
Septembers
2015-05-16 16:08:12 +08:00
Comdex
2015-05-16 16:08:13 +08:00
我也是用方案二,所有请求都返回200,然后在响应里有个status code表明服务请求状态,要不感觉响应里有status code和http 也有状态码是不是多余了?
invite
2015-05-16 16:55:48 +08:00
但是作为服务端更倾向于方案一,因为大多框架和各家提供的API都是这么干的,其实也很简单(先看状态码,然后直接根据状态码决定后续动作)。

这个结论怎么得出来的?
kslr
2015-05-16 16:55:59 +08:00
有些地方直接抛非200状态,JS就傻眼了
invite
2015-05-16 16:57:20 +08:00
补充一点,用HTTP状态码判断,这个方案让人想起了之前那个 @CloudXNS 的API,居然还得用不同的HTTP方法,神一般的设计。
pubby
2015-05-16 17:07:22 +08:00
如果不走HTTPS,会不会有些地方奇葩运营商对一些HTTP状态码进行一些自定义行为
schemacs
2015-05-16 17:24:39 +08:00
@Septembers 多谢,我们现在可能主要不是Web的javascript,而是针对客户端,不过可以按照同样方法处理。200和204之间我们会遵循RESTful惯例。
@Comdex 这个只是方便了客户端而已,一个是http rfc里定义的状态,一个是业务逻辑定义的状态。方案二十忽略了前者。
@invite 框架比如DRF,http://www.django-rest-framework.org/api-guide/exceptions/ ,‘各家’以github为例: https://developer.github.com/v3/#client-errors,你看她其实是没有自己定义业务状态码(服用http已有的),只是定义了出错下不同的message。
@kslr js也可以success,fail啊?
@invite 能给个具体链接吗?不同方法不是本地讨论范围内,那个是RESTful的惯例。
@pubby 这个的确是个问题,多谢提醒,后续如果真出现这样的问题,我们会部署的HTTPS。

另外一点从讨论中开始浮出来了:就是是沿用HTTP规范的状态码(但是自己提供message),还是不用HTTP那套(所有的都用200),自己定一套status code+message?
invite
2015-05-16 17:37:13 +08:00
@schemacs 果然,你说到框架了,哈哈。框架不多说了,每个人有自己的喜好。至于github没有业务状态,那请问如果错误类型较多,怎么办?光靠他返回的英文内容?那国际化问题怎么办?还得配合Google翻译啊?
GhostFlying
2015-05-16 17:49:42 +08:00
@invite 这需要什么国际化,本质上返回的错误信息还是要客户端自己处理掉的,也不是直接返回给用户
schemacs
2015-05-16 17:49:54 +08:00
@invite 错误类型较多?一个HTTP的API如果错误类型超过了HTTP规范里的状态类型,我觉得这个API需要重构了。还有客户端对大部分服务端错误,除了类似临时出错,重试就能解决那些,其他的基本只能友好地提示下用户。github目前没有应该是自定义的错误状态列表,目前我们的逻辑也还还没超过github~ github目前没有做国际化,即使后续国际化,只要服务端检测请求的语言(或者加locale参数),返回对应语言的文本,这个应该也不成问题。
giuem
2015-05-16 17:52:44 +08:00
有些ISP会对非200的状态码返回特殊内容,比如一些广告
schemacs
2015-05-16 18:03:57 +08:00
@giuem 嗯,@pubby已经提醒了我,后续会部署HTTPS。
jokester
2015-05-16 18:18:43 +08:00
HTTP那个是协议层的状态
API可以有符合自己语义的状态
zeayes
2015-05-16 18:29:31 +08:00
@jokester 说的好。

如果使用方案一,前端就不能很好的处理某些较为复杂的业务逻辑了。比如登录接口,到底是”账号不存在“,还是”密码错误“,后端需要根据业务返回不同的错误码,然后前端根据错误码进行对应的业务处理,”账号不存在“,可以跳转到注册页面,“密码错误”可以清空密码,让用户重新输入。
learnshare
2015-05-16 18:36:31 +08:00
一律使用统一的状态码,无需讨论。
mytharcher
2015-05-16 19:11:48 +08:00
HTTP RESTful API 就是针对资源的,协议的状态码也就是资源响应的状态码,其实直接用足够了。如果觉得不够,可以加自定义的小数点进行细分,比如 400.1 代表输入数据格式不匹配,400.2 代表另一个输入数据问题等。

服务端状态的文本消息是没有必要放在响应里传回来的,都应该是前端根据码表对应处理。所以基本不存在国际化的问题。

具体到“登录接口”的“账号不存在”或“密码错误”这种情况,就是对于 session 这个资源创建新的会话没有权限,后端可以用 401 或者 403 来返回状态,而前端拿到状态怎么处理那就随便了。

而前些年大家都用 200 的后端返回,而在数据里再用 `status` 来表示状态,一方面是 RESTful 的理念还没有普及,另一方面也是很多框架不支持,自己实现比较麻烦。现在如果希望设计成 RESTful 的 API,就可以直接使用 HTTP 协议里的很多特性,而没必要再自己定一套规则。
schemacs
2015-05-16 19:12:30 +08:00
@jokester 是的,但是现在客户端开发倾向于不处理前者,指处理后者。
@zeayes 这种复杂情况的确是,我现在能想到就是这个时候再加上具体错误码 {"code": xxx, "message": "username or password is incorret."},而平时没有异常时返回中不额外加code和message(那时候也基本没用),而出错逻辑我们(全局)可以控制,比如自定义exception。
@learnshare 方案一 or 方案二?
schemacs
2015-05-16 19:13:37 +08:00
@mytharcher 你说的最后一段,我深表赞同。
jokester
2015-05-16 19:21:51 +08:00
@mytharcher 有道理
方案2这样在HTTP之上再造协议的方式, 更接近以前的RPC
learnshare
2015-05-16 20:11:03 +08:00
@schemacs
like @mytharcher said,使用 统一的 HTTP 状态码 https://tools.ietf.org/html/rfc2616#section-10
话说大家都不知道协议里规定的状态码?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/191534

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX