例如,您为用户/9运行一个GET请求,但没有id为#9的用户。 哪个是最佳响应码?

200好了 202年接受 204无内容 400错误请求 404未找到


当前回答

TL; diana:

如果在/users/9上没有找到用户,则应该返回404。 如果在/users中没有找到用户?如果Id =9,则应该返回204。

长版:

在回顾了我自己对这些状态代码的使用和本文中的示例之后,我不得不说,如果在/users/9的url上没有找到用户#9,404是适当的响应。

今天在我的系统中,我们的Application Insights日志中充满了数百条记录的404错误,这使我们的日志变得混乱,因为我们决定在/users/9没有相关数据时返回404错误。然而,这并不意味着我们在设置响应时的方法是不正确的,相反,我认为这意味着我们在设置路由时的方法是不正确的。

如果您希望端点获得大量流量,并且担心记录太多404错误,那么您应该更改路由以符合您想要的状态码,而不是强制使用不适当的状态码。

我们已经决定对我们的代码做2个更改:

通过expect /users改变我们的工作路线?id = 9 将我们的错误代码更改为204,这样404就不会填满我们的AI日志。

最后,API的架构师需要了解他们的API将如何被使用,以及哪种路由将适合于该用例。

我相信在/users/9的情况下,您请求的资源是用户本身,用户#9;您要求服务器响应一个标识为“9”的对象,该对象恰好存在于包含单词“user”的路径中。如果没有找到该对象,则应该得到404。

但是,如果调用/users?id=9,我觉得你所请求的资源是用户控制器,同时也提供了更多的专一性,这样它就不会返回所有用户的完整列表。您要求服务器响应一个可以通过查询字符串中定义的ID号识别的特定用户。因此,如果没有找到数据,204对我来说是有意义的,因为即使没有找到数据,控制器也是。

查询字符串方法还完成了一些我认为不仅有助于API开发人员,而且有助于客户端开发人员(特别是初级开发人员或继承这段代码或调用它的代码的未来开发人员):

It becomes immediately clear to anyone involved that 9 is an ID, not some arbitrary number. This point may seem moot in such a basic example, but consider a system that uses GUIDs as row ID's or allows you to get data by a person's name, or even a system that is returning info for specific ZIP/postal codes instead of row ID's. It would be useful for all developers involved if, at a glance, they knew whether that identifying parameter was a first, last, full name, or a ZIP/postal code instead of an ID.

其他回答

使用公共枚举对响应内容进行编码,以允许客户端打开它并相应地派生逻辑。我不知道你的客户如何区分“数据未找到”404和“网络资源未找到”404之间的区别?您不希望有人浏览到userZ/9,并让客户端怀疑请求是否有效,但没有返回数据。

如果仅仅因为没有响应数据而返回404,则任何客户端都会感到非常困惑。

对我来说,响应代码200和一个空的主体足以理解一切都是完美的,但没有数据匹配的要求。

根据w3的帖子,

200好了

请求成功。随响应返回的信息取决于请求中使用的方法

202年接受

请求已接受处理,但处理尚未完成。

204无内容

服务器已经完成了请求,但不需要返回实体主体,并且可能希望返回更新后的元信息。

400错误请求

由于语法错误,服务器无法理解请求。客户不应该在没有修改的情况下重复请求

401年未经授权

请求需要用户身份验证。响应必须包含一个WWW-Authenticate报头字段

404未找到

服务器没有发现任何与Request-URI匹配的内容。没有说明这种情况是暂时的还是永久的

这里有两个问题。一个在标题中,一个在例子中。我认为,这在一定程度上导致了关于哪种反应是合适的争议。

问题标题询问空数据。空数据仍然是数据,但不等于没有数据。因此,这意味着请求一个结果集,即一个列表,可能来自/users。如果一个列表是空的,它仍然是一个列表,因此204(无内容)是最合适的。您刚刚请求了一个用户列表,并得到了一个列表,它只是碰巧没有内容。

相反,所提供的示例询问了一个特定的对象,一个用户/users/9。如果没有找到用户#9,则不返回任何用户对象。您请求一个特定的资源(一个用户对象),但由于没有找到而没有得到它,因此404是合适的。

我认为解决这个问题的方法是,如果您可以在不添加任何条件语句的情况下使用响应,那么使用204,否则使用404。

在我的例子中,我可以迭代一个空列表而不检查它是否有内容,但是我不能在一个空对象上显示用户对象数据而不破坏一些东西或添加一个检查来查看它是否为空。

当然,如果适合您的需要,您可以使用空对象模式返回一个对象,但这是另一个线程的讨论。

现有的答案没有详细说明使用路径参数还是查询参数是有区别的。

In case of path parameters, the parameter is part of the resource path. In case of /users/9, the response should be 404 because that resource was not found. /users/9 is the resource, and the result is unary, or an error, it doesn't exist. This is not a monad. In case of query parameters, the parameter is not part of the resource path. In case of /users?id=9, the response should be 204 because the resource /users was found but it could not return any data. The resource /users exists and the result is n-ary, it exists even if it is empty. If id is unique, this is a monad.

使用路径参数还是查询参数取决于用例。我更喜欢将路径参数用于强制的、规范的或标识参数,将查询参数用于可选的、非规范的或属性参数(如分页、排序区域设置等)。在REST API中,我会使用/users/9而不是/users?Id =9,特别是因为可能嵌套获取“子记录”,如/users/9/ SSH -keys/0获取第一个公共SSH密钥或/users/9/address/2获取第三个邮政地址。

我更喜欢使用404。原因如下:

Calls for unary (1 result) and n-ary (n results) methods should not vary for no good reason. I like to have the same response codes if possible. The number of expected results is of course a difference, say, you expect the body to be an object (unary) or an array of objects (n-ary). For n-ary, I would return an array, and in case there are not results, I would not return no set (no document), I would return an empty set (empty document, like empty array in JSON or empty element in XML). That is, it's still 200 but with zero records. There's no reason to put this information on the wire other than in the body. 204 is like a void method. I would not use it for GET, only for POST, PUT, and DELETE. I make an exception in case of GET where the identifiers are query parameters not path parameters. Not finding the record is like NoSuchElementException, ArrayIndexOutOfBoundsException or something like that, caused by the client using an id that doesn't exist, so, it's a client error. From a code perspective, getting 204 means an additional branch in the code that could be avoided. It complicates client code, and in some cases it also complicates server code (depending on whether you use entity/model monads or plain entities/models; and I strongly recommend staying away from entity/model monads, it can lead to nasty bugs where because of the monad you think an operation is successful and return 200 or 204 when you should actually have returned something else). Client code is easier to write and understand if 2xx means the server did what the client requested, and 4xx means the server didn't do what the client requested and it's the client's fault. Not giving the client the record that the client requested by id is the client's fault, because the client requested an id that doesn't exist.

最后一点:一致性

GET /用户/ 9 PUT /users/9和DELETE /users/9

PUT /users/9和DELETE /users/9已经必须在成功更新或删除的情况下返回204。如果用户9不存在,它们应该返回什么?根据所使用的HTTP方法将相同的情况显示为不同的状态代码是没有意义的。

Besides, not a normative, but a cultural reason: If 204 is used for GET /users/9 next thing that will happen in the project is that somebody thinks returning 204 is good for n-ary methods. And that complicates client code, because instead of just checking for 2xx and then decoding the body, the client now has to specifically check for 204 and in that case skip decoding the body. Bud what does the client do instead? Create an empty array? Why not have that on the wire, then? If the client creates the empty array, 204 is a form of stupid compression. If the client uses null instead, a whole different can of worms is opened.