2

在一个真正安静的应用程序中,我应该通过链接访问我的资源,而唯一的“神奇的已知 URL”应该是应用程序入口点。直接查询GET /user/john应该在至少有一个链接之后发出,/user或者作为前一个链接指定的搜索 url 的结果,比如GET /user?username=john

但随着以下链接强制要求更多功能、更多开发时间和更智能的客户端,实际情况是我编写和使用的大多数 RESTful api 都是部分 RESTful 的:它们是定义良好的 URI 和方法的集合,所有这些都是以前已知的通过一些文档给用户。最后,大多数RESTState Transfer含义并不存在。

好吧,遵循以前已知 URL 的现实,404代码变成了一个问题:如何区分404可能具有的 2 种含义:

  • 一个正确404的意思是“找不到资源,但你可以在以后再试一次”。示例:GET /user/mario虽然 mario 不是注册用户

  • api 的错误使用意味着“这里永远找不到资源,你错误地使用了这个 API”。例子:GET /foobar/123

区分这两种情况很重要,因为作为服务维护者,他们基本上告诉我这是一个预期错误,我不应该担心(第一种情况)或意外错误,我应该担心与我的服务集成客户有问题(第二种情况)

我尝试寻找更好的状态码来代表第二种情况,我找到的最接近的状态码是406 Not Acceptable(但它是指向Accept无法实现的标头的响应)和410 Gone(由于没有资源,可能会令人困惑,但好的部分是它告诉客户端永远不要再尝试该 URL)。然而,两者都不足以解决这个问题

你是如何或将如何解决这个问题的?

侧节点python eve是一个有趣的项目,它试图成为一个 restful api 的State Transfer部分。它为此实现了 HATEOAS

4

2 回答 2

2

What about using 403 for the first case (together with the explanation) and 404 for the second? Since the RFC 403 refers to 404 as an alternative response code they might be related...

403 Forbidden: The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information available to the client, the status code 404 (Not Found) can be used instead.

403: You understand what the client wants but refuse to fulfill it. The client should not try again - it's forbidden until this resource is created - which you can explain as part of the answer.

404: You know that the client wants something you won't provide and can tell him in good faith, that this resource will never exists.

Update:

RFC 2119 explains how the "SHOULD NOT" has to be interpreted:

SHOULD NOT This phrase, or the phrase "NOT RECOMMENDED" mean that there may exist valid reasons in particular circumstances when the particular behavior is acceptable or even useful, but the full implications should be understood and the case carefully weighed before implementing any behavior described with this label.

I think for your use case this is true. The client request shouldn't be repeated *without solving the reason stated in the 403 answer: "accessing this resource is forbidden because no user named mario exists". But if the client is sure that the reason went away, he is free to try again. But this might be only my interpretation of the 403 "should not be repeated" statement.

于 2013-10-12T18:11:13.290 回答
1

根据RFC 2616 第 10.4.5 节的设计,无法区分这两个原因:

10.4.5 404 未找到

服务器未找到任何与请求 URI 匹配的内容。没有
说明这种情况是暂时的还是
永久性的。

如果服务器通过一些内部可配置的机制知道旧
资源永久不可用并且没有转发地址,则应该使用 410 (Gone) 状态代码。
当服务器不希望
确切地揭示请求被拒绝的原因
或没有其他
响应适用时,通常使用此状态代码。

于 2013-10-12T17:55:31.137 回答