HTTP GET请求状态码204与404的区别

60

我有两个资源用户和专辑。用户有一个专辑列表。获取专辑的方式有两个REST API。

  1. user/{userId}/albums/{albumId} 通过专辑ID获取专辑。如果未找到则返回404
  2. user/{userId}/albums 通过用户ID获取所有专辑。在这种情况下,如果用户没有专辑,应该是状态码204还是404?
6个回答

65
如果专辑列表为空,是否应该将其视为错误?假设专辑以JSON数组返回,对于这种情况的常见响应是使用HTTP 200并将空数组作为主体返回。
返回404表示该资源不存在,有点像在说特定用户的专辑列表甚至不可能询问。但实际上,成功返回专辑列表是可能的,只是列表为空。我认为这一点并不特别异常。这与使用不存在的ID(使用其他端点)检索特定专辑完全相反;在这种情况下,404才是正确的。
虽然204比404更好,因为它至少告诉客户端请求成功但没有内容,但它的意图并非真正用于表示“成功的缺席”。相反,它表示资源确实存在,但由于某种原因服务器选择不在响应体中包含资源-例如请求的目的可能仅是向客户端传递一些标头。
204还可以用作对POST请求的响应,在该请求中服务器执行了某些操作,而不必创建任何新资源(这将暗示201 CREATED),或者由于某些其他原因不相关返回任何资源。
我认为你需要的是一个
GET /user/xxx/albums

HTTP/1.1 200 OK

[]

11
状态码为 200 表示请求成功,并且响应中有数据。但是在这种情况下,响应中没有数据,因此正确的状态码应该是 204。如果您调用了 GET /user/xxx/albums,其中 xxx 是一个不存在的用户,那么我会返回一个 404 状态码,并附上一条消息说明未找到哪个资源。由于这是一个 GET 请求,不会与通常情况下 POST 返回 204 的典型场景产生混淆。总之,您的 API 应该有文档告诉开发人员针对特定请求使用的状态码的含义。 - The Muffin Man
20
我不同意。有数据,一个空数组。我认为强制客户端将一个完全有效的列表查询(暂时为空)视为“错误”非常奇怪,所以我们一致同意排除404。然而,对我来说,204具有特殊用途,即当客户端实际上不想要或不能获得任何资源时使用。大多数API都会使用一个空数组,我不明白为什么会引起任何争议。在普通客户端编程中,你更喜欢使用null还是空列表? - JHH
是的,抱歉,我在你回复时正在更新我的答案。最初的评论太快了... - JHH
1
我明白你的意思。我想,与其返回一个空数组并返回200,我通常选择返回204并在响应正文中不返回任何内容。 - The Muffin Man
唯一不应该发生的事情是返回带有验证错误的200,除此之外,返回空集合是可以的,因为这符合用户的要求。 - Bartłomiej Sobieszek
1
我认为204不是没有找到专辑的最佳响应,因为它强制消费者为该状态码做特殊安排。如果使用空数组的200,则其最常见的快乐路径可以保持不变:arrayItem => doSomething(),如果为空,则永远不会执行任何操作。我知道HTTP协议和消费者逻辑之间存在分离,但我认为代码应该为消费者服务,而不是使其更加困难。 - smurtagh

33

以下是定义HTTP协议的RFC2616对状态码的说明:

The first digit of the Status-Code defines the class of response. The last two digits do not have any categorization role. There are 5 values for the first digit:

  - 1xx: Informational - Request received, continuing process

  - 2xx: Success - The action was successfully received,
    understood, and accepted

  - 3xx: Redirection - Further action must be taken in order to
    complete the request

  - 4xx: Client Error - The request contains bad syntax or cannot
    be fulfilled

  - 5xx: Server Error - The server failed to fulfill an apparently
    valid request
在您的情况下,请求已成功,但没有相册可显示,因此您应该使用2xx类别中的状态。以下是RFC对204状态的说明:服务器已满足请求,但不需要返回实体主体,并可能希望返回更新的元信息。响应可以包括新的或更新的元信息,以实体标头的形式呈现,如果存在应与所请求的变体相关联。如果客户端是用户代理,则不应从导致发送请求的文档视图更改其文档视图。此响应主要旨在允许进行操作的输入而不会导致用户代理的活动文档视图发生更改,尽管任何新的或更新的元信息都应用于用户代理当前处于活动视图中的文档。204响应不得包括消息正文,因此始终在标题字段后的第一行为空行时终止。RFC指出,204主要旨在允许输入,因此您不应使用此选项。在这种情况下,我会使用200。

1
值得考虑的情况是,先前请求用户所有相册的内容已经返回并被缓存。如果随后删除了该用户的所有相册,则对于后续请求用户相册列表的响应返回204,告诉用户代理“不应该改变其文档视图,因为这会导致请求被发送”,因此客户端的相册列表视图将不会反映为空列表。 - adk
我只希望在这种情况下永远不会出现204 - 这将使事情变得简单。一个带有200的空响应就足够了。顺便说一句,为什么rest api必须关心消费者的视图是否需要更改呢?rest api的返回代码只应允许消费者清楚地解释资源的状态,而不是定义客户端视图应该转换到什么。 - code4kix

23

404错误码

当用户尝试访问一个已经失效或不存在的链接时,网站服务器通常会生成一个“404 Not Found”网页。

204返回码

服务器已经满足了请求,但不需要返回实体主体。

结论

显然您需要返回204状态码。如果使用404,则可能会使用户感到困扰。而且,仅当目标专辑不存在时才使用404。将1和2都使用404是不合适的。


如果适用于JSON,则返回一个空的JSON对象,否则返回那个。 - guillaume31
那么 Rest Api 端点永远不会返回 404,因为路由是手动定义的?只有在使用未定义的 URL 或在分布式系统中不可用的情况下,服务器才会引发 404。 - FishingIsLife

8

当你请求一个特定的资源,比如一个用户,但该用户不存在时,应该返回404状态码。例如,你有一个API可以使用以下URL检索用户:

https://yourdomain.com/api/users/:userid

如果请求检索不存在的用户1234,则应返回404。在这种情况下,客户端请求了一个不存在的资源。

https://yourdomain.com/api/users/1234 
404

现在假设你有一个API,该API使用以下URL返回系统中的所有用户:

https://yourdomain.com/api/users

如果系统中没有用户,在这种情况下应返回状态码204。

说得好。谢谢。 - amacrobert
2
错误,服务器能够理解您尝试访问的资源,并且可以根据URI确定哪个进程,因此不应使用404。 - João Carlos Brasileiro

6

让我来谈一下我的看法。希望你已经知道404与204之间的区别。

404状态码

404表示资源未找到或不存在,或URL无效。

例如:

GET : https://api.myapp.io/product/product_id_123
GET : https://api.myapp.io/image/nokia.jpg

如果单个产品/资源项目在数据库或资源文件夹中不存在,这意味着此URL的资源无效,因此我们必须抛出404错误。搜索引擎如Google和Bing将不会缓存结果,并且不会在第二天重试以获取新鲜内容。

204状态码

204表示URL有效,服务器已成功执行,但没有数据返回。

例如:

GET : https://api.myapp.io/product/search?keyword=nokia

如果在数据库中没有匹配关键词的数据(单个或多个)返回结果,则抛出 204 ,因为没有数据可返回,但 URL 仍然有效,搜索引擎(如 Google 和 Bing)将在第二天重新尝试获取新鲜内容,对于他们来说这不是无效的 URL,当您在第二天重试时可能会有一些数据与查询相匹配。


那很有道理,谢谢。 - Naseem Ahamed

0

我同意回答,但我认为是204或200,这取决于您在专辑列表为空时的响应。

如果您将返回一个空数组,则使用200代码返回它,如果您不想返回任何内容,则正确的选择将是204。(我更喜欢使用带有空列表的200)

只有在资源不存在时才使用404,如果是空列表,请选择204或200。

祝你好运!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接