区分REST状态代码

时间:2019-03-19 16:08:06

标签: rest http

最近,我开始向响应中添加状态代码,而不是直接返回它们。

让我们假设/person/1从数据库返回一个ID为1的人。如果此人不存在,我应该返回404状态吗?如果服务器上不存在端点或资源不存在,我应该如何区分?

现在,让我们假设我有一个用于插入用户的POST端点。如果该端点检查电子邮件格式是否正确并且我返回400,该怎么办?我怎么知道请求的格式是否正确,没有路由到任何servlet或是否确实到达了确定电子邮件格式错误的servlet?

是否总是从我的所有servlet返回200 OK响应是一个好习惯,表明无论结果如何,应用程序都已完成工作,并在json字段status中写入状态,或者这是一个过大的杀伤力和反模式?

我对HTTP服务器没有太多的经验和知识,所以我不确定我是否在正确解释(也没有使用它),因此我对此表示歉意。

3 个答案:

答案 0 :(得分:2)

  

让我们假设/ person / 1从数据库返回一个ID为1的人。如果此人不存在,我应该返回404状态吗?如果服务器上不存在端点或资源不存在,我应该如何区分?

对于客户端而言,资源或端点是否不存在并不重要。服务器告诉我们的是,对于给定的URI,没有可用的表示形式。

正如inf3rno所述,通常会向客户端提供客户端直接在响应中服务器需要的所有URI。通过将书签添加书签或在某些外部资源中包含链接,某些链接可能会随着时间的推移而变得无效,因此404 Not Found响应仅通知客户端对于给定URI没有可用的表示形式。

通常,客户端也不会对API的内部感兴趣,而只是发送或接收可以使用的数据。

不幸的是,许多用户还有一个误解,就是他们已经承担了某些资源来返回某些types。如果预期的表示形式发生更改,则此类类型可能会导致客户端失败。除此以外,URI结构本身(包括任何路径,矩阵和查询参数)不应用于推断API的任何逻辑结构,其公开的端点或资源的逻辑结构到该API的其他资源。 URI整体上是指向资源的指针。资源可能有数十个指向它的链接。您可能会认为URI是返回的表示形式的缓存键,在连续调用时,该缓存将进一步由缓存而不是实际的服务器提供服务。这实际上是REST施加的限制之一,并已在Web上广泛使用。

  

现在,让我们假设我有一个用于插入用户的POST端点。如果该端点检查电子邮件格式是否正确并且我返回400,该怎么办?我怎么知道请求的格式是否正确,没有路由到任何servlet或是否确实到达了确定电子邮件格式错误的servlet?

RFC 7231POST定义为万能工具,如果其他方法不适合当前任务,则应使用该工具。它明确声明该方法提供的有效载荷将为processed according to the resource's own specific semantics。因此,如果您需要在保留用户的电子邮件地址之前或在开始计算,后台进程或其他任何操作之前验证用户的电子邮件地址,请这样做:)即使PUT(通常被认为仅替换当前地址)也是如此。在请求中使用给定的表示形式不仅被允许,而且还被鼓励对服务器对目标资源的任何约束进行验证,因此它应拒绝不符合其期望的有效负载。

此处的精髓是,服务器应始终向客户端提供尽可能多的信息,以使客户端确定下一步要做什么。想一想您可以通过浏览器访问的基于Web的应用程序。如果收到400 Bad Request,浏览器通常会告诉服务器该请求不满意的地方,即语法不完整或必填字段的值缺失。 REST API也是如此,因为它们基本上只是Web上使用的交互模型的概括。因此,适用于Web的相同概念也适用于REST:)

通过这种方式,每个HTTP状态代码都有其自己的语义,并应帮助客户端确定客户端下一步应该做什么。 400 Bad Request即表示服务器由于服务器认为是基于客户端的错误而无法或不会处理该请求,并且由客户端来纠正该故障并重新发送请求。

另一方面,405 Method Not Allowed指示客户端使用了目标端点不支持的HTTP方法。错误响应不仅向客户端指示该错误,还向Alllow响应标头内的目标端点允许哪些方法。

RFC 7231中指定的每个HTTP状态代码都有自己的语义,建议至少浏览一下它们。您还可以在IANA上查找所有可用的状态代码,这些代码提供指向描述这些状态代码的规范的链接。

  

始终从我的所有servlet返回200 OK响应是一个好习惯吗,它表明应用程序已完成其工作而不管结果如何,并在json字段状态中写入该状态,或者这是过大和反模式?

与错误代码一样,成功代码(在200范围内)也具有自己的语义。如果创建新资源作为处理请求的结果(通过PUTPOST),则应向客户端通知201 Created状态响应,该响应还包含HTTP Location标头,其中包含以新创建的资源为目标的URI。

如果服务器可能需要一些时间来计算响应,则可能建议返回202 Accepted响应,以将未决请求通知客户端。客户端可以稍后在某个阈值期之后或在服务器通过回调机制(例如电子邮件通知或类似内容)收到通知后,轮询请求。由于德国法律的限制,即德国公司必须保留通过EDI交换的邮件的档案。作为EDI提供商,我们提供给我们的客户通过触发我们的HTTP端点之一来对其交换的消息进行存档。根据该公司交换的消息数量和应为存档选择的时间段,此过程可能需要一些时间(更具体的是几个小时),而不是让客户等待该时间段,我们只是简单地返回202 Accepted,然后从后面开始归档过程。根据配置,他们要么轮询完成的存档,获取有关最终​​结果的信息,要么在文件不大的情况下直接通过电子邮件发送存档。

如果客户端对资源执行更新,

204 No Content也非常有用。由于PUT通常定义为用有效负载中提供的表示替换当前表示,因此,在收到204 No Content响应后,客户端知道服务器已应用更新,并且当前表示的确类似于请求的表示由客户。因此,服务器不需要进一步通知客户端当前表示的外观,因为客户端已经知道其外观。但是,如果服务器不得不将有效负载转换为可能导致其他结果的其他表示形式,则在200 OK响应(包括表示形式)内通知客户端有关资源的新状态可能是有益的更新过程的结果。

返回200 OK失败,包括带有指出错误的字段的JSON负载,这肯定是错误的处理方式。它不仅会给客户端一个错误的提示,而且响应也可能会被中介程序缓存并返回给其他请求此请求的客户端,即使失败可能只是暂时的(DB崩溃等)。此外,这种JSON负载可能使用非标准格式,因此需要带外知识才能实际处理消息。虽然我们人类有能力弄清楚发生了什么,但计算机本身还不那么聪明。

我希望您能看到HTTP在何时使用哪种方法或响应代码方面提供了很多语义。它们在那里是有原因的,因此在适当的情况下也应使用它们。

答案 1 :(得分:1)

在GET请求中,404状态只是一个响应代码。如果找不到提供的ID的记录,则必须在响应的正文中提供错误消息。

对于POST请求,您可以返回400错误代码,并在正文中指定缺少或失败验证的字段。

对于未找到的网址,用户将始终获得404错误代码。

对于成功的GET或POST请求,您可以返回状态为200的响应

答案 2 :(得分:1)

  

如果端点不存在,我应该如何区分   服务器或资源不存在?

在这种情况下,端点是Web资源的IRI(URI)。如果端点不存在,则很有可能该Web资源也不存在。这是一种不太可能的情况,因为您是从服务器(HATEOAS)获取URI的,但是如果两个请求之间发生了某些变化(例如, URI模板更改或有人删除资源。在所有这些情况下,404都是不错的HTTP状态代码。您可以详细说明错误消息,也可以使用其他错误代码,但是对我而言,这是没有意义的,因为URI模板更改是罕见的事件。不过,这将使客户端更加灵活,因为它可以清除缓存并使用新的链接重试。