首页 > 解决方案 > HTTP 和 REST:状态代码与请求相关还是与资源相关?

问题描述

在使用 HTTP 的 REST 中,状态代码是与请求相关还是与资源相关?

在非 REST HTTP 请求/响应调用中,状态码指的是请求的成功/失败/等等。请求失败是因为客户端发送了无效请求吗?然后返回 400,以此类推。

但是在 REST 中,URI 被声明为引用“资源”,并且状态码通常似乎用于引用资源(即,它是关于资源的元数据)。但是如果获取资源的请求失败了,客户端怎么知道是资源有问题,还是只是获取资源的请求有问题呢?

我的问题是 - 我理解正确吗?如果是这样,如果请求在服务器端失败会发生什么?

例子:

我的问题是最后一个请求 - 返回200 OK似乎适合 Web 请求,但它包含的唯一正文是有关失败的信息。

标签: resthttpasynchronous

解决方案


TL;博士

HTTP 响应代码属于为请求发出的响应,而不是资源本身


不幸的是,人们对 REST 是什么以及不是什么存在着广泛的误解。

正如Jim Webber正确指出的那样,HTTP 是一种应用协议,其领域是通过网络传输文档,我们推断的任何业务活动都只是实际文档管理的副作用。因此,我们的任务是将这些副作用缩小到有用的范围内。

REST 或更准确地说,REST 架构是一组约束,主要通过依赖标准化的文档类型/表示格式和类似于 Web 上使用的交互模型来处理客户端与服务器的解耦。这里的主要目标是允许服务器在未来自由发展,而不必担心引入的更改会破坏客户端,因为它们只在他们能够理解并能够处理的标准化文档格式上运行。通过精心设计并专注于上述标准化格式,应保证不同系统之间的互操作性。

例如,REST 非常关注服务器如何教客户他们下一步可以做什么。Jim Webber 将其与基于文本的计算机游戏进行了比较,在该游戏中,您可以选择下一步该做什么。他后来还举了一个典型的基于 Web 的类似 Amazon 的结帐示例,在该示例中,您按照给定的预定义结帐协议进行操作,直到您以某种方式到达该状态机的末尾。

强烈提示 HTTP 响应代码属于为请求发出的响应,而不是资源本身,即当您将资源隐藏在某些身份验证之后。在第一个请求中,您不包含AuthorizationHTTP 请求标头,这会导致401 Unauthorized状态代码。您的浏览器现在将要求您输入用户名和密码,输入后将重新发出相同的请求,但这次Authorization设置的标头可能会成功,具体取决于您的输入和/或服务器实现。

如果请求在服务器端失败会发生什么?

HTTP 基于请求-响应模型,这意味着对于每个请求都必须发出响应。如前所述,此处返回的 HTTP 状态代码充当协调元数据,允许客户端对其进行操作。即,在上面带有401 Unauthorized状态代码的示例中,浏览器(客户端)要求发送凭据并重新发出请求。

此外,使用的每个 HTTP 操作都包含一些定义的属性,客户端可以假设它们为真。服务器是否坚持这些是另一回事,但表现良好的服务器应该这样做。这样的性质是safetyidempotency。入门者确实保证在处理使用此类操作发出的请求时不会更改资源状态。这里突出的例子是GETHEAD用于检索文档。Itempotency 是一个在网络连接出现问题时很有用的属性,并且客户端无法确定请求是完全到达服务器还是只是响应在中途丢失了。它基本上允许服务器重新发送请求而无需进一步考虑,因为无论初始请求是否在服务器上处理,这里的结果应该是相同的。PUTDELETE经常在这里用作示例。

不幸的是,其他 HTTP 操作(例如POSTPATCH不具有此类属性)。因此,如果出现网络问题,客户端无法确定是否可以自动发出请求。即,如果在执行订单和稍后重新发送请求时出现网络问题,服务器可能已经接受了两次订单。因此,如果应该执行一些重要的事情,例如支付、扩展订单等,最好使用幂等操作,即使用POST-PUT 创建模式

防止处理某些请求的进一步解决方案是将它们作为包含或类似请求标头的条件请求发送。但是,如果应该对非常特定的资源状态执行某些不安全的操作,通常会使用此方法。即补丁通常取决于当前的签出版本。如果同时对远程状态进行了一些更改,我们通常不希望将补丁应用于更改后的版本,因此希望请求失败,这会迫使我们下载新状态并修改请求方式,以便预期的结果将如预期的那样。ETagIf-Modified-Since

根据你的问题:

202 Accepted虽然与响应标头结合起来似乎很自然Location,但不幸的是,RFC 7231 没有提到位置标头是202 Accepted响应的要求,也没有提到标头的定义Location表明它可以在202 Accepted响应中使用,因此,根据 a来自 Roy Fielding 的响应Location外部的标头和201 Created响应标头没有定义的含义。您可以返回一个包含资源状态标头的响应代码,而不是最初返回一个,然后它可能会返回一个状态,然后像您一样执行到最终状态的重定向。3xxLocation202 Accepted303 See OtherLocation202 Accepted

我的问题是最后一个请求 - 返回 200 OK 似乎适合 Web 请求,但它包含的唯一正文是有关失败的信息。

根据RFC 7231

与此响应一起发送的表示应该描述请求的当前状态并指向(或嵌入)一个状态监视器,该监视器可以为用户提供对何时完成请求的估计。

因此,如果长时间运行的进程(部分)处理失败,则有效负载本身可能会指示开始处理失败。您还可以执行重定向到资源,然后返回4xx包含即应用程序/问题+json响应有效负载的状态代码,提示处理失败的原因等。


我觉得 202 不适合 GET 请求,所以我会返回 200 和状态负载,直到返回重定向有意义?

的实际定义202 Accepted

202(Accepted)状态码表示请求已被接受处理,但处理尚未完成。该请求最终可能会或可能不会被执行,因为在实际进行处理时它可能会被禁止。HTTP 中没有用于从异步操作重新发送状态代码的工具。

202响应是故意不置可否的。它的目的是允许服务器接受对某个其他进程的请求(可能是一个每天只运行一次的面向批处理的进程),而不需要用户代理与服务器的连接持续到该进程完成。与此响应一起发送的表示应该描述请求的当前状态并指向(或嵌入)一个状态监视器,该监视器可以为用户提供对何时完成请求的估计。

因此,根据您对request has been accepted for processing部分的解释,您可以202 Accepted为 GET 请求返回 a,因为实际过程可能仍未完成,或者返回200 OK响应。我认为这里的重要部分是客户理解并知道如何处理和解释的媒体类型(又名表示格式)的使用。基于该响应,客户端应该知道实际过程是否已完成,无论是否失败,还是仍处于未决状态。我不得不承认,我目前不知道有任何合适的媒体类型可以用来表达这些知识。


推荐阅读