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站发帖,如有没说清楚或者违反社区原则的地方,请大家不吝指出。

28928 次点击
所在节点    程序员
65 条回复
learnshare
2015-05-17 11:35:29 +08:00
我想问支持 200 的这些朋友,你在家说方言,出门也说方言么?
pysama
2015-05-17 11:35:45 +08:00
有没有同学从老板的角度说说看法呢?
两种方案对于产品的影响是什么?哪种方案的ROI更高?(毕竟技术是为产品服务嘛~~)

我突然想到某位晋升很快的一个朋友说过“技术只是手段”,我觉得我们可以多从其他角度想想。
或许再回过头来看,就会有种感悟——“不用在意那些细节”

当然,我上面说的话,可能,对于大部分开发者来说,都是不中听的。
我非常理解,那就请你们多包涵。

不说了~~
invite
2015-05-17 11:59:17 +08:00
@schemacs 你真应该好好读下 @way2exluren 的回复。

你刚才引用的 "v2 will always return a 409 status code with a stable and documented error identifier in the body." 人家也是有错误ID返回的。 按你之前的意思,这是不是也算 “自己造” 了?
jokester
2015-05-17 12:08:05 +08:00
@pysama
老板没做过, 从管理角度看恐怕方案2开发成本要低些
RESTful那一套是对HTTP的横向扩展, 吃透需要开发者有不坏的sense
方案2是在HTTP上层扩展, 没那么多要求

从技术面来看
Dropbox的服务是关于文件的, 他的API的语义天然地接近HTTP Resource, 不另外做扩展层有利于从HTTP的特性得益(如cache)
但是如果我要做的API不需要cache呢? 如果我的API甚至不是关于某种资源呢? 强行REST的好处在哪?
twitchgg
2015-05-17 14:29:15 +08:00
http://events.linuxfoundation.org/sites/events/files/slides/Andrei_Shakirin_REST_CXF.pdf
这里有个基于Apache CXF JAX-RS框架的restful api设计指南。感觉能帮到你
schemacs
2015-05-17 15:22:33 +08:00
@mengzhuo 那个bug有人同问后,官方给出方法是自己重写方法去实现的。
@learnshare 赞同,尽量用大家认同的,不够用了再自己搞私有的(业务)状态码。
@invite 嗯,是的,出错时会有detail和code,但是这个情况只在HTTP状态码不能满足的情况下。
@pysama 没有老板,只有技术哈
@jokester 嗯,我们目前没打算用HTTP以外的,至少API层(其他数据,如日志,推送等另说)。
@twitchgg 多谢,大致看了下,正常情况下也是纯数据,只有出错时才有status和message。
zhicheng
2015-05-17 15:32:24 +08:00
1,HTTP 是给使用 HTTP 的业务设计的,这也是为什么它是“应用层协议”。
2,如果不能理解第一点,那么请在心里默念100遍,"设计HTTP协议的人比我聪明"。
mthli
2015-05-17 16:33:36 +08:00
用方案一吧。写个API库封装一下,这样客户端用的开心你们也开心。我以前尝试给Dribbble API封装库的时候就是选择方案一的。
jarlyyn
2015-05-17 16:42:41 +08:00
这个话题快赶上php是最好的语言了。
poke707
2015-05-17 18:07:33 +08:00
status code 应该只用来表达通讯状态,业务状态你可以放在response header自定义一个X-XXX-code
sunus
2015-05-17 19:31:06 +08:00
http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api

这篇文章做了一些总结。理论上应该用状态码。实践上用envelope返回状态码的非常多。个人也不觉得有什么本质区别,更多是一种风格和约定。

我觉得主要是json response没有一个普遍采用的标准。 有一些标准但没有被广泛采用 http://stackoverflow.com/questions/12806386/standard-json-api-response-format
jokester
2015-05-17 19:41:04 +08:00
@zhicheng
按这个逻辑, 发明HTTP的人想必是觉得自己比发明TCP的聪明
izhaohui
2015-05-17 19:53:58 +08:00
说一下我的经历,从前一个项目的开发一直是用200状态加json 返回的形式做的,前端开发人员写ajax代码也都从来不写错误回调而是依赖全局的错误回调,有一次一个新模块实验性上restful,结果那几天前端像疯了一样抱怨你们的接口都不能用,各种4xx,5xx的错误,结果是我们在响应体封装了消息他们都不看,只说这样的不合理。感觉我们的接口质量很差,然后新模块就继续json + 200了。感觉也是一个接受程度的问题,在他们的观念里只要不是200一定是你后端问题,说明你接口不稳定。而不考虑是我们把错误信息传递到了另一个层面。
schemacs
2015-05-17 20:37:18 +08:00
@sunus 第一个链接不错,我现在做法是只有出错时才带Envelope。JSONP是个问题,但是暂时用不到。
miukal
2015-05-17 21:02:41 +08:00
对于这个问题,首先两种方式肯定都可以实现业务的,而且实现难度并没有很大差别,维护难度可能也没有很大差别。restful 只是一种约定,一种选择,不一定在所有情况下都"更好"。
对于开发者自身来说,这个约定目前比较流行,了解一下是应该的。
但在实际工作的项目中做出选择,需要考虑自己的工作环境。如果项目相关开发人员都了解并认可这种约定,那么就使用,因为不会带来很多额外成本。如果处在一个项目相关开发人员不了解,也没有愿望去了解和接受这个新约定的环境下,使用这个约定可能就是给项目找麻烦了。
elvba
2015-05-17 21:12:09 +08:00
我觉得这就是理想和现实的差别,作为服务端,先假设所有服务端开发者都能完全理解并实现 RESTful API,但是对于前端开发者,APP 开发者来说,很多人都不知道 HTTP 协议,他们不需要也没必要了解 HTTP 协议的具体内容,只需要知道能请求某个地址,获取到结果就行了。所以具体实践的时候遭到反对也是必然的了。
再说服务端,说自己的 API 是 RESTful 风格的,以及打算使用 RESTful 设计 API 的,或者正在这么实践的同学们,你们真的觉得自己实现了完整的 RESTful API 了么?这是个需要多次实践才能把握的东西,没有谁能保证一上手就能做好吧,和写代码一样,过段时间就会发现之前不好的地方,但是 API 又不能随便改,只能等下次大版本更新的时候来改了。
最后,RESTful 只是一个风格而已,实际开发中还是怎么好用怎么来的好。
elvba
2015-05-17 21:13:28 +08:00
@miukal 赞同!
refresh
2015-05-17 21:16:59 +08:00
用http status code,客户端封装一个函数即可、
odirus
2015-05-17 22:31:21 +08:00
GET、POST都傻傻分不清的人大有人在,之前在组上提过用 RESTful 的方式来实现API,后来终于说服他们了,他们在代码中新建了一个名字叫做 REST 的模块。。。。这就是我们的RESTful API,现在新进来成员的时候我都要花费口舌来介绍为啥我们的框架里面有个叫做REST的模块。醉了。
pi1ot
2015-05-17 22:46:30 +08:00
@giuem 是的,非200返回码经常被ISP和浏览器拦截处理。

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

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

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

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

© 2021 V2EX