RESTful 的增删改查成功应该返回什么状态码? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Vimax
V2EX    Java

RESTful 的增删改查成功应该返回什么状态码?

  •  
  •   Vimax 2020-07-14 15:13:54 +08:00 11780 次点击
    这是一个创建于 1918 天前的主题,其中的信息可能已经有所发展或是发生改变。

    RESTful 的 GET POST PUT DELETE 如果操作成功应该返回什么状态码呢?

    用 200,201,202,204 代表 4 种请求的成功合适吗?

    请求成功

    • GET 200 OK
    • POST 201 Created
    • PUT 202 Accepted
    • DELETE 204 No Content
    • 如果 GET POST PUT   DETELE 请求,数据库执行结果都为 0.又如何返回 HTTP 状态码呢?

      是返回 404 not found 吗?

      另外一个问题

      请求方式的数据类型: GET 和 DELETE 是否[不能]或[不推荐]使用 JSON 数据的形式.

      前端使用的是 VUE axios 发送请求,之前 DELETE 发送 JSON 数据,后端无法接收到.

      目前 4 种请求方式对应使用的数据类型是:

      • GET application/x-www-form-urlencoded
      • POST [ "application/json;charset=" ]
      • PUT [ "application/json;charset=" ]
      • DELETE application/x-www-form-urlencoded
    132 条回复    2020-07-16 10:37:35 +08:00
    1  2  
    hantsy
        1
    hantsy  
       2020-07-14 15:33:58 +08:00   1
    Spring 内容协商规律:

    Get , Accept: application/json
    POST,PUT Content-Type:application/json
    DELETE 不用管。

    实现:
    https://github.com/hantsy/spring-reactive-jwt-sample/blob/master/src/main/java/com/example/demo/web/PostController.java

    各种情况状态返回参考测试代码:

    https://github.com/hantsy/spring-reactive-jwt-sample/blob/master/src/test/java/com/example/demo/IntegrationTests.java
    qdzzyb
        2
    qdzzyb  
       2020-07-14 15:34:23 +08:00
    成功统一 200 就可以了
    Vimax
        3
    Vimax  
    OP
       2020-07-14 15:46:15 +08:00
    @hantsy 学习了.谢谢兄弟.
    Vimax
        4
    Vimax  
    OP
       2020-07-14 15:46:46 +08:00
    @qdzzyb 这样语义不清晰吧.
    bxb100
        5
    bxb100  
       2020-07-14 15:49:16 +08:00
    @Vimax #4 统一返回 200, 然后返回定义的 业务 code 处理错误
    chendy
        6
    chendy  
       2020-07-14 15:52:25 +08:00
    get 和 delete 默认没 body,指定 application/x-www-form-urlencoded 没用
    hantsy
        7
    hantsy  
       2020-07-14 15:53:22 +08:00
    在 Spring 3 。x 的时候都是要自己配置,现在自动内置了 Content Negotiation 内容。

    https://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc/

    对于 REST API,内容协商主要就是根据 Accept (返回内容可接受的格式) 和 Content-Type (请求的内容使用格式) 来决定 mediatype 。

    一般情况下:

    GET, 前端需要设置 Accept: application/json
    POST,PUT 前端需要设置 Content-Type:application/json
    DELETE 不用管。

    如果有特例,特殊要求,比如 POST 有返回内容,那么 Accept,Content-Type,甚至你可以用不同的格式。

    Accept:applicaiton/xml
    Content-Type:applicaiton/json

    这个依赖你后端是否能够处理。
    baiyi
        8
    baiyi  
       2020-07-14 16:01:33 +08:00   2
    状态码是根据不同的接口有不同的响应。

    GET 200 不必多说。

    POST 也有很多种形式,如果是正常创建并需要返回创建结果的,可以使用 201 Created
    如果是异步处理,提前响应结果的,需要使用 202 Accepted
    如果是正常处理,不需要响应结果的,需要响应 204 No Content
    如果是正常处理,但结果不方便直接响应,需要返回 205 Reset Content,提示 Client 重新获取

    如果你想写一个非常标准的 HTTP API,那就需要学习每个状态码所代表的含义,不能与请求方法一一对应
    如果不想这么费劲,因为确实也没多少人在乎,那就完全可以直接 200,也没问题
    hantsy
        9
    hantsy  
       2020-07-14 16:03:16 +08:00
    对于 Accept,Content-Type,Spring 的 Controller 方法 @RequestMapping (或者其它 GetMapping,xxx 等) 可以设置 produces,consumes 属性对应处理。

    Accept ---------------produces
    Content-Type----------consumes

    默认情况下,现在 Spring 处理过于宽松,什么格式都放进来。严格的情况下最好指定 Mediatype,对于一些不支持格式,前端访问 API 时,Spring 会更快速的响应,返回 415 。
    jones2000
        10
    jones2000  
       2020-07-14 16:38:22 +08:00
    你返回数据结构里面应该有一个状态码, 这些查询或操作失败的, 最好是返回 200 ok, 然后内有有一个状态码来表示具体的错误码,好点的还有一个错误的描述字符串, 方便前端提示给客户,否则都是 404,客户直接抓瞎了。
    hantsy
        11
    hantsy  
       2020-07-14 17:39:57 +08:00
    @jones2000 404 怎么会抓狂???

    /posts/anoneexistingpost 是一个不存在的 Post
    /users/noneexistignuser 是一个不存在的 User
    /products/noneexiting 是一个不存在的产品
    /orders/noeexiting 是一个不存在的订单
    hantsy
        12
    hantsy  
       2020-07-14 17:41:58 +08:00   2
    不同的路径下 404 的意义已经将不同的 Resource 区分的很清楚,只有 SB 才用 200 返回一切数据。
    wangyanrui
        13
    wangyanrui  
       2020-07-14 17:44:46 +08:00
    全部 200,自定义 code

    另:前面的兄弟们吵起来不要带上我~
    zhuweiyou
        14
    zhuweiyou  
       2020-07-14 17:48:21 +08:00   2
    国情是全部 200,你搞各种状态码,前端要骂你的。
    qdzzyb
        15
    qdzzyb  
       2020-07-14 18:03:32 +08:00
    @Vimax #4 不会不清晰吧 GET 200 POST 200 PUT 200 DELETE 200 这四个表示的是四个语义吧
    一般前端喜欢 统一返回 200 body 里{code: 0, data: xxx} 或者 {code: xxx, err_msg: "error message"}
    EminemW
        16
    EminemW  
       2020-07-14 18:08:41 +08:00 via iPhone
    不是应该 http 状态码描述请求状态 自定义业务状态码描述业务状态么
    hantsy
        17
    hantsy  
       2020-07-14 18:28:40 +08:00
    @qdzzyb
    @zhuweiyou 你们公司由前端决定系统架构吗?由前端来定交互协议?
    hantsy
        18
    hantsy  
       2020-07-14 18:39:24 +08:00
    Angular 中 httpclient 处理 API 使用 Rxjs Obseverable, subscribe 中 next 和 error 天然分开处理。

    用 axios 访问 API 的话,then 里面正常业务,catch 处理异常。

    代码清楚可见。

    全部返回 200 就会部跑到 then 里面, 代码变成屎一样。哪个前端喜欢写这样的屎?我听到很多前端抱怨过后端写的什么垃圾都塞进 200 body,自己拿到还要先判断。

    自己的懒惰,无知和无能非要说成什么国情,前端需要。
    wanacry
        19
    wanacry  
       2020-07-14 18:39:57 +08:00 via iPhone
    参考 es 的
    xlinux
        20
    xlinux  
       2020-07-14 18:41:41 +08:00 via Android
    400 会不会被打?
    pwli
        21
    pwli  
       2020-07-14 18:44:10 +08:00 via Android
    如果要上监控和重试的话,失败请求不建议返回 200
    hantsy
        22
    hantsy  
       2020-07-14 18:47:37 +08:00
    @xlinux https://www.restapitutorial.com/httpstatuscodes.html 这个页面标星基本都是最常用的。4xx 系列之前项目还用到
    422 Unprocessable Entity (WebDAV) 输入验证异常用上了这个。
    402 Payment Required

    405,406,415 这种基本都是非法调用,框架会提示你。
    ChanKc
        23
    ChanKc  
       2020-07-14 18:49:52 +08:00
    @pwli 是的,我最近打算上一些日志分析就发现。
    如果一些错误用 400,直接打 access_log 里面,然后用标准的 access_log 分析工具分析就能看到一些数据
    要是都是 200,还要造一堆轮子
    ChanKc
        24
    ChanKc  
       2020-07-14 18:54:57 +08:00
    @qdzzyb 我作为前端,很不喜欢统一 200
    如果用 axios,我要自己封装 Promise 异常
    如果用 service worker 做缓存,我 fetch 完了还要把 body 用 json()拿出来判断一下才能决定要不要缓存
    qdzzyb
        25
    qdzzyb  
       2020-07-14 18:58:31 +08:00
    @ChanKc #24 其实我也不喜欢都返回 200 尽量能用状态码就用状态码
    hantsy
        26
    hantsy  
       2020-07-14 18:58:50 +08:00
    @ChanKc 除了 ELK, EFK 之类的,可以看看现在的云服务,PagerDuty, DataDog 之类。
    qdzzyb
        27
    qdzzyb  
       2020-07-14 19:00:43 +08:00
    @hantsy #17 前面开发的大佬用了这一套,前端也都封装好了
    bigWolf999
        28
    bigWolf999  
       2020-07-14 19:01:19 +08:00
    还有一个问题,数据量大且结构复杂的请求数据是否只能将 GET 改为 POST 呢?
    labulaka521
        29
    labulaka521  
       2020-07-14 19:02:09 +08:00
    习惯就好,上面那个说别人 SB 才是个大 SB
    passerbytiny
        30
    passerbytiny  
       2020-07-14 19:03:42 +08:00 via Android
    不想细分就 200,想细分就 20*,*具体是哪个前面有人回复过了。

    成功统一 200 ( OK ),错误统一 500 (服务器内部错误),也是符合 RESTful 的,只不过 500 太多显得服务器很无能。


    至于“全部 200”这样的回复,劝一句楼主,不要跟闭眼抄作业的人玩。
    happypy1
        31
    happypy1  
       2020-07-14 19:59:35 +08:00
    如果你的 GET 是来搜索的话,即使你没有找到数据,你应该返回 200 OK,因为 200 意味着你的搜索请求,服务器执行成功了。而且像这种搜索 endpoint 的话,你应该是返回一个空的数组,如果没有找到资源的话。

    但是如果你的 GET 是要拿一个具体的资源的话,比方说你知道 ID:GET /custoemrs/1,后端要是没有找到,就应该返回 404 。否则就返回 200 。

    202 一般是用于表示后台已经接受了你的数据,但是还没有处理完成。参考一下[MDN]( https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/202)

    如果你只是简单的创建或者更新数据的话,200 即可。
    xuanbg
        32
    xuanbg  
       2020-07-14 20:00:12 +08:00
    @passerbytiny 全部 200 的意思是只要服务能够正常访问就返回 200 。http 的状态和业务的错误分开。
    daimubai
        33
    daimubai  
       2020-07-14 20:08:29 +08:00   1
    我们项目:
    请求成功统一 200
    客户端错误统一 400
    服务端错误统一 500
    系统异常错误999
    hantsy
        34
    hantsy  
       2020-07-14 20:48:24 +08:00
    @labulaka521 神经病
    renmu123
        35
    renmu123  
       2020-07-14 20:50:24 +08:00 via Android
    v2 周经贴
    hantsy
        36
    hantsy  
       2020-07-14 21:00:08 +08:00
    @bigWolf999 有些 API 有一个专有的 _search endpoint,比如 /products/_search,可以看看 MS API 设计(被 REST 之父喷过),还包括各种比较,逻辑操作等,太复杂了,query params 表达不了,这种 POST 方便。
    hantsy
        37
    hantsy  
       2020-07-14 21:02:19 +08:00
    @qdzzyb 后端 java Spring,我之前也见过这种神封装,好好的 ResponseEntity 带个套,所有的 Controller,所有方法返回用一个 Util 套一下。
    labulaka521
        38
    labulaka521  
       2020-07-14 21:07:29 +08:00 via iPhone   2
    @hantsy nmsl
    hantsy
        39
    hantsy  
       2020-07-14 21:14:38 +08:00
    @labulaka521 就你这样,我真替你父母感到悲哀。
    在工作中,你就是我说那种人,狗屁正事做不了,借口比谁都多的巨婴,整个公司估计也没人待见你。
    jones2000
        40
    jones2000  
    2020-07-15 00:52:50 +08:00
    @hantsy “不同的路径下 404 的意义已经将不同的 Resource 区分的很清楚,只有 SB 才用 200 返回一切数据” 你这种方式我没看到过,太高级了, 我还不会用,特别是如何把 sql 的执行错误的详细信息如何返回给前端然后提示客户。

    数据库执行错误就几十种, 主键冲突, 表不存在,账号没有写权限等等,还要具体错误信息。

    像以下的详细的错误应该如何通过你的 404 返回给前端
    1. “ALTER TABLE `xxxx_db`.`STOCK2604` DROP PRIMARY KEY
    Can't DROP 'PRIMARY'; check that column/key exists”

    2. “ALTER TABLE`xxxx_db`.`STOCK2604`ADD PRIMARY KEY(`ORGID`,`SECCODE`,`ENDDATE`,`F001V`,`F004V`)
    Specified key was too long; max key length is 767 bytes”

    3. “SELECT CAST(CONV(HEX(MAX(`XDBMASK`)),16,10)AS UNSIGNED),CAST(CONV(HEX(MIN(`XDBMASK`)),16,10)AS UNSIGNED)
    FROM`xxxxxx` WHERE CAST(CONV(HEX(`XDBMASK`),16,10)>0
    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 2”
    newtype0092
        41
    newtype0092  
       2020-07-15 01:03:36 +08:00
    @jones2000 别问,问就是需求不合理。
    什么样的需求才叫合理?只提标准 RESTful 能直接实现的需求,其他的不做就完事了。
    你看 XX 大厂 RESTful 都能满足需求,你们需求还能比人家复杂?

    可以和同行讨论观点,不要和教徒争论信仰。
    jones2000
        42
    jones2000  
       2020-07-15 01:22:24 +08:00
    @newtype0092 谁发我工资 谁的需求就合理。 我只是打工的, 只会具体到一个一个需求的实现才能拿工资糊口。太空泛的概念对我没什么用, 还是要能实现具体需求才行呀。哪有直接对老板说你的需求不合理,不做。现在工作不好找难呀。
    lihongming
        43
    lihongming  
       2020-07-15 02:42:44 +08:00 via iPhone
    全用 http code 做状态码是一种理想,实际很难做到,因为你总会有一些非标准的或是需要细分的状态。

    所以还是 http 的归 http,业务的归业务就好,不要被那些鼓吹纯 http code 的人吓到,须知任何事情走向极端都是邪教。更何况很多大公司的 API 也在这么做(比如 amazon ),你不是一个人!
    hantsy
        44
    hantsy  
       2020-07-15 08:13:20 +08:00
    @jones2000 如果我没记错的话,V 站几乎都是 Spring 。Spring 的 ExceptionTranslator 会将所有的所有的数据库异常翻译成相应的 DataAcessException (子类),而在 Spring Boot 中所有的内置的异常 Spring 已经处理了。

    数据库异常问题,这类的系统问题根本就不应该丢给前端,常识,自己从项目一开始就要有自己的日志分析处理系统,监控日志。

    再说了,你的这些例子就是程序错误,你们不写测试吗?
    IvanLi127
        45
    IvanLi127  
       2020-07-15 08:18:57 +08:00 via Android
    @zhuweiyou #14 那是掉队的野生前端吧
    crclz
        46
    crclz  
       2020-07-15 08:19:26 +08:00
    200:成功
    401:Unauthorized 未登录
    403:Forbidden 没权限操作资源
    404:NotFound,一是由框架在无法匹配路由时抛出,二是当 PATCH or DELETE /article/{id}时 id 找不到的时候返回。
    400:其他错误情况。这个里面要自己设计数据结构以便细分,例如{code: UsernameNotFound, message: 用户名不存在}
    hantsy
        47
    hantsy  
       2020-07-15 08:27:21 +08:00
    Amazon 最新一代的 API 还没完成(没完全覆盖所有业务),上一代(现在通行)基于十几年的开发结果,不必细说。Http Status 处理,Github API 是典范,Github 返回的异常结果也有业务 code,但是仅针对 Httpstatus 表达不了的状态,作一个补充,现在 Github 也提供了新的 GraphQL 。
    hantsy
        48
    hantsy  
       2020-07-15 08:31:31 +08:00
    @crclz 这个还不错。

    尽可能利用 HttpStatus,比如用户注册,Email 已经存在,返回 Conflict 状态 ,这种表达更直接。POST 数据验证 Validation 失败,可以用 Unprocessable Entity,这些状态的字面意义才是对错误异常的说明起到真正辅助作用。
    hantsy
        49
    hantsy  
       2020-07-15 08:33:17 +08:00
    hantsy
        50
    hantsy  
       2020-07-15 08:40:18 +08:00
    我不懂的是这些状态的字面意义这么清晰的情况下,完全抛弃不用,还要定义自己所谓的业务码,返回 200,把整个系统代码(前后端)搞成一锅粥。业务参考码我也会用一些,但会参考 Github,仅仅在一些通用错误下作补充说明,比如一些 400 太不清晰,其它的能用 HttpCode 一律不用业务码。

    国内,这几年仅仅在上海做过两个创业项目,也是严格按我第一帖子的状态来写的,老板好像不会管你用什么方法解决,所以写成这样,公司老板是不应该背锅的。
    hantsy
        51
    hantsy  
       2020-07-15 08:44:19 +08:00
    结帖。
    itechify
        52
    itechify  
    PRO
       2020-07-15 09:01:42 +08:00 via Android
    去年某段时间的周经贴
    ragnaroks
        53
    ragnaroks  
       2020-07-15 09:09:47 +08:00
    草,只有我用自定义状态码?
    yaphets666
        54
    yaphets666  
       2020-07-15 09:40:45 +08:00
    统一返回 200 是最好了 你返回其他的状态码 有些状态码都到不了 js 里 直接被浏览器处理了 200 是前人实践出来的
    matenshi
        55
    matenshi  
       2020-07-15 09:55:23 +08:00
    成功就 20x (不过不会像主楼说的那样区分), 不成功看情况,40x,500 之类的(并返回错误信息)
    Airon
        56
    Airon  
       2020-07-15 10:13:12 +08:00
    成功 20x 错误 40x, 后端业务错误 500,具体业务错误 {code:, message: } 。基于工作环境的水平吧,大类错误码大家知道自带含义,那它就能起到辅助作用。
    cruii
        57
    cruii  
       2020-07-15 10:39:07 +08:00
    全部返回 200,结果后端出错封装一个自定义错误码。
    这种就很让人不舒服,HTTP 规范告诉我请求成功了,结果后端告诉我请求出错了。
    binux
        58
    binux  
       2020-07-15 10:55:34 +08:00   2
    @yaphets666 不会可以闭嘴
    akira
        59
    akira  
       2020-07-15 11:19:33 +08:00
    @cruii 应该是指成功返回 200, 不成功的返回才使用别的
    yaphets666
        60
    yaphets666  
       2020-07-15 11:21:01 +08:00
    @binux 小伙子年轻吧 没遇到过运营商劫持非 200 返回的情况吧 你不知道别人为啥都 200 你最好别自己找自己的路 跟着别人走也许不太对 但绝对不至于出什么大事
    binux
        61
    binux  
       2020-07-15 11:25:18 +08:00
    @yaphets666 “直接被浏览器处理了”???
    还有现在还不上 https 的公司就别呆了。
    libook
        62
    libook  
       2020-07-15 11:30:20 +08:00
    HTTP 是通信协议,建议将协议上的状态与业务上的状态分开,所以 HTTP 的返回状态码最好严格按照 HTTP 标准来使用,涉及到业务状态的最好在返回结果里用额外的状态标识来标识。

    比如 DELETE,服务器执行成功,且返回 Body 有内容,则返回 HTTP 状态码 200 (其他情况参考 2xx 段各个状态码的定义),返回的 Body 里用字段或对象来体现业务上的状态,是有记录且成功删除了,还是成功执行了但无可删除记录,还是删除错误 1 、删除错误 2 等等。
    4xx 段在标准中表示的是因客户端错误导致的非预期的请求,这就看你如何定义这个 API 了,比如 API 的 URI 被视为一个确定的资源,如 /user/12345,那么业务上可以定义为使用 DELETE 方法是建立在 ID 为 12345 的这个 user 资源存在的基础上的,那么 HTTP 协议上可以首先考虑这个资源是否存在,如果不存在的话,业务上可以认为这个资源不存在客户端就不应该发出这个请求,就按照 HTTP 标准返回 404,告诉客户端它发出的这个请求有问题。

    这些都不是固定死的,关键是一套系统的 API 应该有统一的一套自己的标准。
    比如你定义除了创建以外,任何对于资源的直接操作都应该基于资源存在的基础,资源不存在一律返回 404 状态。
    然后系统内所有 API 都按照这个标准来设计就可以了。
    REST 只是一套帮助你设计自己系统 API 标准的思想,最终还是要为业务服务的,如果其思想与业务需求相矛盾,就没必要硬上 REST 风格。
    wangyzj
        63
    wangyzj  
       2020-07-15 11:32:01 +08:00
    200
    libook
        64
    libook  
       2020-07-15 11:37:52 +08:00
    可能写得有点长,核心没表达清楚。

    返回 404 是因为“需要告诉客户端它犯了个(请求的资源不存在的)错误”,而不是因为“这个资源不存在”;同样的,返回 200 是因为“需要告诉客户端这个请求成功了(且不属于其他 2xx 状态码的情况)”,而不是因为“业务成功了”。

    可以细细品一下。
    baiyi
        65
    baiyi  
       2020-07-15 11:38:31 +08:00
    @bigWolf999 #28 query 过多且过于复杂时,可以使用查询语言类协议,比如 GraphQL
    RJH
        66
    RJH  
       2020-07-15 15:03:12 +08:00
    直接 200,然后在响应体里面返回定义业务状态码,不懂就参考微信、阿里的接口
    zsdroid
        67
    zsdroid  
       2020-07-15 15:14:40 +08:00
    别人来讨论问题,总有一些人以为自己很牛逼,一上来就喷。别人反喷他一下,他就急了。
    zsdroid
        68
    zsdroid  
       2020-07-15 15:19:42 +08:00
    iugo
        69
    iugo  
       2020-07-15 15:27:27 +08:00
    @libook

    - 需要告诉客户端它犯了个(请求的资源不存在的)错误
    - 这个资源不存在

    我觉得这两个难以区分.

    我认为我理解你想要表达的, 就是协议统统 200, 不需要 404, 除非 API 路由都不对, 才会 404.

    但这种设计不符合 RESTful, 这里不是说 RESTful 绝对正确, 而是不符合 RESTful.
    iugo
        70
    iugo  
       2020-07-15 15:29:36 +08:00
    如果把 HTTP 状态码当作后端错误代码的分类, 这样似乎就很好理解.

    我是不建议弃用 HTTP 状态码, 只用 200 的.
    frankwei777
        71
    frankwei777  
       2020-07-15 15:44:04 +08:00
    我前端 成功只见过 200
    markliu2013
        72
    markliu2013  
       2020-07-15 15:44:15 +08:00
    @hantsy

    /posts/anoneexistingpost 是一个不存在的 Post
    /users/noneexistignuser 是一个不存在的 User
    /products/noneexiting 是一个不存在的产品
    /orders/noneexiting 是一个不存在的订单

    这种返回 404 是最佳实践吗?我觉得 404 是告诉客户端,他请求的接口不存在,但是 /posts/这个接口是存在。比如本来一个 user 资源是存在的,但是被另一个用户删除了,这时候在请求就会 404,客户端就会感觉莫名其妙。

    比如在一个 MVC 的架构里面,请求 users.php?id=1,但是 id 为 1 的 user 不存在,这时候能返回 404 吗?
    hantsy
        73
    hantsy  
       2020-07-15 15:53:04 +08:00
    @markliu2013

    /posts/<id 或者 id 对等物,比如 Slug>, 如果这个 ID 不存在,返回 404, 这个意思。你还在武汉?微信或者邮件聊吧。
    hantsy
        74
    hantsy  
       2020-07-15 15:57:57 +08:00
    @markliu2013 或者你看直接代码吧。
    markliu2013
        75
    markliu2013  
       2020-07-15 16:01:41 +08:00
    技术问题就这里聊聊吧。
    我的意思是 404 在这里是否是最佳实践的设计。因为这个接口本身是存在的,也去数据库查询了,但是查询结果是空集合。

    我找到了这个问题:
    https://stackoverflow.com/questions/11746894/what-is-the-proper-rest-response-code-for-a-valid-request-but-an-empty-data
    目前有说 404,但是也有说用 204 或者 200
    hantsy
        76
    hantsy  
       2020-07-15 16:02:12 +08:00
    >404 Not Found: The requested resource could not be found but may be available again in the future.

    就是表示你访问的时候资源不存在。
    hantsy
        77
    hantsy  
       2020-07-15 16:04:51 +08:00
    @markliu2013 你说的 Users.php? 的情况是集合,永远返回 200,即使是空的 Body,除非有其它逻辑出玩异常要处理。

    posts/:id 表示单个资源。
    hantsy
        78
    hantsy  
       2020-07-15 16:06:28 +08:00
    目前我所用的 404 都是会定位到单个资源上操作上 get, put, delete,找不到的时候都返回 404 。
    hantsy
        79
    hantsy  
       2020-07-15 16:10:33 +08:00
    集合查询结果为空用 204 感觉有点牵强,用 json 的话,它是一个空的数据 [] ,这个内容长度不是 0 。
    zsdroid
        80
    zsdroid  
       2020-07-15 16:18:45 +08:00
    @cruii HTTP 规范告诉你请求成功了,结果后端告诉你业务出错了。没毛病吧。
    难道实际上请求成功了,却告诉你请求失败了才对?
    est
        81
    est  
       2020-07-15 16:22:52 +08:00
    @hantsy 呵呵。订单 200 表示存在,404 表示不存在,那已拆分订单如何表示?

    硬用 4 个动词+几个有限的状态码去套真实世界的业务模型才是 sb 。
    zsdroid
        82
    zsdroid  
       2020-07-15 16:25:05 +08:00
    2014 年,某网友:其实所谓的restful更适合那些总想着沽名钓誉的硕士研究生们去堆砌辞藻,用来体现出自己比其他众多工程技术人员“高人一等”。
    一开始以为其只是个喷子,对其所说不以为然,一笑而过。
    如今看来,这位网友说的太对了。就像某位“大佬”一样,restful确实可以高人一等。
    zsdroid
        83
    zsdroid  
       2020-07-15 16:26:32 +08:00
    hantsy
        84
    hantsy  
       2020-07-15 16:30:07 +08:00
    我突然发现定制 HTTP 标准定制者,REST 之父 Fielding 博士都不如你们。
    @zsdroid
    @est
    hantsy
        85
    hantsy  
       2020-07-15 16:31:30 +08:00
    在你们的世界,只要一个请求方法,一个状态,所有问题都可以解决,全世界做技术都是 SB 。
    markliu2013
        86
    markliu2013  
       2020-07-15 16:34:37 +08:00
    @hantsy REST 给安卓和 iOS 端使用,有啥问题吗?
    RoyceLee
        87
    RoyceLee  
       2020-07-15 16:35:10 +08:00
    话都不要说满了,历史的滚滚车轮会告诉我们,当时认为是对的,可能是大错特错的。
    hantsy
        88
    hantsy  
       2020-07-15 16:41:03 +08:00
    @markliu2013 没有问题。

    但是如果移动端原生开发,可以选择其它协议,不一定要用 REST 。

    RSocket 直接用 TCP,原生效率更高。
    WebSocket ( web,Android 原生都是可以用),这个我以前做过一个聊天游戏的后端。

    当然我以前是主张混合使用,实时用 WebSocket 交互,一般用 REST 。
    libook
        89
    libook  
       2020-07-15 16:42:00 +08:00
    @iugo

    - 告诉客户端它犯了个错误
    - 业务上这个资源不存在

    把括号里的去掉可能更突出重点? HTTP 4xx 状态表示“Client Error”,所以主要是突出客户端犯了错误,即客户端在当前情况下不应该发送这个请求。
    如果你认为当前客户端发这个请求完全合理,在预期正常的情况下,那么就返回 2xx 。

    我没有说“协议统统 200,不需要 404”,事实上你返回 200 还是返回 404 都是可以的( REST 根本就没定义应该返回什么,它也完全不 care ),完全取决于你是否认为这个情况是客户端的错误;关键是系统上所有接口得统一起来,哪些情况一律返回 200,哪些情况一律返回 404.

    REST 只是个风格,而不是标准。
    [Roy Thomas Fielding 博士的论文]( https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)第 5 章描述了究竟什么是 REST 风格,但是篇幅非常短,即便是第 6 章的实践部分也没有详细介绍 REST 的最佳实践。
    论文前面章节提到了 API 设计的一些问题,而 REST 本身就是为了解决这些问题而提出的思路而已,只要是按照这种思路去设计 API,就是 RESTful 的,就能享受到 REST 带来的收益。

    如果认为一种设计违背 Roy Thomas Fielding 博士对 REST 风格的定义,可以引用论文里的段落来说明。

    当然如果把某企业或某项目的 REST 实践当做标准的话,就没有什么可讨论的了。
    est
        90
    est  
       2020-07-15 16:43:51 +08:00
    @hantsy Fielding 这货在 Adobe 最自鸣得意的发明是 Coldfusion 。也没见你来天天吹呢?
    libook
        91
    libook  
       2020-07-15 16:44:29 +08:00   1
    忘了这不能用 markdown 语法。。。

    Roy Thomas Fielding 博士的论文
    https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm
    est
        92
    est  
       2020-07-15 16:46:25 +08:00
    其实 Fielding 发明 RESTful 有一个极其狭窄的用途,那就是最老派的 HTTP 资源。什么是资源?就是文件。所以 RESTful 最成功的应用应该是 WebDAV 。这跟 Coldfusion 的设计也是一脉相承的。然而现代 web 早就进化得连妈都不认识了。你们还抱着 CGI 时代的老掉牙概念到处吹 B 。

    以我的觉得,读操作走 GET,写操作走 POST,其余放在 JSON 里拉倒。
    xuanbg
        93
    xuanbg  
       2020-07-15 16:48:31 +08:00
    @binux 这个和 https 没关系,你可以尝试以移动 APP 或者服务间调用的角度来看这个事情。因为业务层逻辑不想也不应该关心传输层的事情,是的,除了 web 外,其他调用者使用 http(s)协议只是为了传数据而已。如果不同情况下返回的数据类型不统一,处理起来就很麻烦。所以才有只要请求正常,就是 200 这种方案。
    对于 web 来说,可以很方便处理 http status,不同的 status 比较优雅。但对于其他端来说,这就是灾难。
    hantsy
        94
    hantsy  
       2020-07-15 16:54:02 +08:00
    @libook Richardson Mature Model 具体的可用于 REST 设计的指导性原则。

    https://martinfowler.com/articles/richardsonMaturityModel.html

    Fielding 那个博士论文主要讲一些 REST 特性。
    lbunderway
        95
    lbunderway  
       2020-07-15 17:03:07 +08:00
    我们也是统一 200 再由业务 code 区分 哈哈
    hantsy
        96
    hantsy  
       2020-07-15 17:17:03 +08:00
    恰好我用过 Allaire Jrun,所以我知道 CodeFusion 也是 Allaire,但我没有用过。后来( 20 年前左右) Allaire 被 Macromedia 收购。CodeFusion,Jrun 这些服务器都是被边缘化。

    到了后来,Adobe 并购 Macromedia,早就没有这些产品。

    请问 Fielding 是怎么跑到 Adobe 公司去做 CodeFusion 产品???
    @est
    maigebaoer
        97
    maigebaoer  
       2020-07-15 17:18:54 +08:00 via Android
    所有都是 200,加一个返回码。反正我受不鸟这种,但是公司要用。
    est
        98
    est  
       2020-07-15 17:24:37 +08:00
    > 请问 Fielding 是怎么跑到 Adobe 公司去做 CodeFusion 产品???

    @hantsy 这个我就不知道了。毕竟 adobe 里只有 ColdFusion 没有 CodeFusion 。
    takemeaway
        99
    takemeaway  
       2020-07-15 17:27:50 +08:00
    老问题了,你想用什么就用什么,不能自由选择就按照公司给你的标准来。
    hantsy
        100
    hantsy  
       2020-07-15 17:30:26 +08:00
    @est 没错,这个你对了,我写错了,是 ColdFusion,一般简写 CF 。这个产品明明是 Allaire 的,那请问怎么变成 Fielding 在 Adobe 期间的得意作品。

    Adobe 并购 Macromedia 才几年而已。
    1  2  
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     987 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 22:37 PVG 06:37 LAX 15:37 JFK 18:37
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86