哪个HTTP状态码表示“暂时无法使用,请稍后再试”?

225
我正在开发一个RESTful API,其中http://server/thingyapi/thingyblob/1234 返回与项目#1234关联的文件(也称为“ blob”)以供下载。但是在文件生成之前可能会发出请求。它肯定将来会可用。
服务器上有一个批处理过程生成所有的blobs。项目1234已经存在,并且除了blob之外的数据已经可用。服务器只是尚未生成1234的blob。
我不想返回404;那是给不存在的东西使用的状态码。这个东西将会存在,但是还没有生成。就像“处理中”的YouTube视频一样。 我认为重定向代码也不适合;因为没有“其他”URL可尝试。
在这种情况下返回正确的HTTP状态码是什么?

3
与此有关这个链接是关于如何使用REST实现长时间搜索的最佳实践建议。 - Rob Hruska
8
首先,如果 thingy 1234 还没有任何 GET 可用的表示形式,那么从客户端的角度来看,它作为一种资源存在的意义是什么?服务器内部存在一个排队的作业来创建 1234,并不意味着资源 1234 存在。其次,客户端从哪里获取到 URI .../thingyblob/1234?直到资源实际上可以被 GET,服务器可能不应该向客户端提供该 URI。 - Andy Dennie
4
204 "No Content"表示服务器已成功处理请求,但当前并未返回任何内容。 - Timo
1
客户端在服务器准备好之前请求了资源。如果您将此视为过早的请求,则是客户端的错误,正确的答案是“202-已接受”。如果您将此视为太晚的资源生成,则是服务器的错误,更适合使用“503-不可用”。任何一种都可能是正确的答案。我认为“稍后重试”的方面更多地属于5xx而不是2xx,因此我会选择503。 - GlenPeterson
2
还有其他人觉得我们需要对使用了20多年的HTTP响应代码进行重大更新吗?我发现它们非常有限且容易引起误解(尤其是在处理API响应时)。 - Jeremy Holovacs
显示剩余4条评论
8个回答

101
“问题”实际上出现在服务器端:客户端发出了一个格式良好的请求,但服务器无法满足它。因此,我倾向于使用“服务器错误”,即5xx状态码。
引用RFC 7231(当前的HTTP标准,重点添加):
“5xx(服务器错误)状态码表示服务器意识到它出错或无法执行所请求的方法。除非响应HEAD请求,否则服务器应发送包含错误情况的说明以及它是临时还是永久条件的表示。”
注意:
- “出错或无法执行请求”:尽管它们被称为“服务器错误”,但它们不仅适用于服务器错误。 - “临时或永久”:这些代码适用于像您这样暂时不可用的资源。

在所有可用的状态码中,我认为503, "Service Unavailable"最适合:

503(服务不可用)状态码表示服务器由于暂时超载或计划维护而当前无法处理请求,在一段时间后可能会得到缓解。服务器可以发送Retry-After头字段...建议客户端在重试请求之前等待适当的时间。

注意:

  • "likely be alleviated after some delay": 对于你的情况是正确的。
  • "temporary overload": 对于你的情况来说不是严谨的。但是可以这样解释,如果你的服务器速度更快,当客户端发出请求时批量处理已经完成,所以它是一种“过载”:客户端要求资源的速度比服务器能够提供的速度更快。
  • 重试对于你的服务是合适的,因此你的回复应包括一个Retry-After值。你可以将估计的批处理下一次执行的完成时间或批处理执行间隔作为值提供。
定义自己的5xx状态码(例如591),虽然允许,但语义是错误的:

客户端必须理解任何状态码的类别,如第一个数字所示,并将未识别的状态码视为该类别的x00状态码的等效状态码

客户端会将您自己的状态码视为500,“内部服务器错误”,这是不正确的。

4
我不认为它比HTTP 202更好:http://benramsey.com/blog/2008/04/http-status-201-created-vs-202-accepted/ - JCCyC
4
@JCCyC的博客提出了一个好的理由,即对于创建请求(POST或PUT),返回202响应。这个问题似乎是在询问GET请求返回什么。 - Raedwald
4
注意: "Retry-After" 也可以与 307 - 临时重定向 配合使用,如果您想在资源“准备就绪”期间强制客户端等待其他位置,则这非常有效。 - rloth
4
这不是服务器的问题。5xx状态码不应被使用。这种情况是系统中预期和有效的状态。部分生成的记录并不等同于部分功能的服务器。客户端也没有问题。他们正在请求一个将在某一时刻存在的有效资源,因此不应使用4xx状态码。服务器的响应应该是“好的,但我仍在处理中”(202已接受)。 - Jared Deckard
2
@JaredDeckard 不,我不能同意202 - 除非更改端点的文档。如果端点是“给我x”,那么不,我们不会给你x,并且给出x不是可以稍后完成的“过程”。但是,如果端点被描述为“准备资源y的表示x”,那么好吧,服务器正在准备一个资源,该资源已经存在,以客户端请求的形式,但它还没有准备好。但是我想补充说,5xx错误并不意味着服务器有问题,就像您所暗示的那样。503表示客户端应该重试。 - AnorZaken
显示剩余4条评论

92

我建议使用202 - 已接受。根据文档

请求已被接受处理,但处理尚未完成。[...] 它的目的是允许服务器接受某个其他进程的请求(可能是一天只运行一次的批处理进程)。


116
这对于最初创建“thingy#1234”的请求是有意义的,但不适用于之后发出的针对“thingy#1234”本身的GET请求。特别是,202表明作为GET请求的结果,服务将在稍后的时间点发送“thingy#1234”的数据。这是不正确的。 - Sam Harwell
11
它还说:“返回此响应的实体应包含请求当前状态的指示,以及指向状态监视器或一些估计的指针,以便用户知道何时可以期望请求被满足。” 因此,这是告知客户端blob尚未准备就绪以及查找它何时准备就绪的好方法。 - Remy Lebeau
6
我认为,“已接受处理”表示您正在保存请求以便稍后进行处理。如果只是被忽略了,您应该返回4xx或5xx代码,告诉客户端他们可能需要再试一次。 - Luke
5
有时候,即使它在WebDAV规范中,处理状态码102似乎也是一个合理的选择。 - akostadinov
9
完全不同意这个答案。服务器没有返回任何内容,也不打算返回(因为这个请求没有做任何处理 - 它在GET请求中本应该如此)。因此,客户端某种程度上无法访问该资源。这应该被视为一种错误,因此不适用2XX代码,而应该使用4XX或5XX空间中的代码。该请求实际上被丢弃了,没有“被接受进行处理”。 - Adam
显示剩余2条评论

46

我认为423 - Locked可以用于此目的:

423(已锁定)状态码表示方法的源或目标资源已被锁定。此响应应包含适当的前置条件或后置条件代码,例如“lock-token-submitted”或“no-conflicting-lock”。


1
非常好的回答!我想知道为什么它没有更多的赞。 - lex82
19
可能是因为它是一个WebDAV HTTP代码吗? - Stephan L
2
从akka-http中,有StatusCode RetryWith = reg(c(449)("Retry With", "应在执行适当的操作后重试请求。"))其中该操作将是等待和重试。 - ozma
3
在很多方面我同意这个观点。我有一个类似的情况(在我的情况下,从可能尚未填充的索引中搜索)。从语义上讲,我认为这是正确的。然而RFC 423指出:“此响应应包含适当的前置条件或后置条件代码,例如'lock-token-submitted'或'no-conflicting-lock'”。不确定如何在这里应用它。个人而言,我会选择409冲突状态码,但是该提议已被否决,没有任何注释-不确定为什么? - Adam
1
4xx状态码的问题在于它们暗示着“客户端不应该在未修改请求的情况下重复发送此请求”。来源:https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400 “Not Ready Yet”是一个服务器端的问题,因此必须使用5xx状态码,而503状态码是最合适的选择,不需要重定向和缓存。 - GlenPeterson
显示剩余6条评论

33

我不想返回404响应;那是用于不存在的物品。

该URL并不对应一个请求的物品。

http://服务器/thingyapi/thingyblob/1234

客户端正在请求一个名为thingyblob的物品,但该物品不存在。如果存在,你会将其提供给他们。

404。


4
我很高兴有人说了这个!我无法相信有这么多人认为 503 是一个合适的响应。更不用说其他一些奇怪的建议了。 - Jason Desrosiers
2
我认为这是最好的答案。你可以在404响应中返回一个主体。该主体可以指示该物品将在以后的日期可用。或者也可以使用Retry-After头。标准需要在这里进行一些扩展,因为它不能很好地涵盖这种情况。 - WW.
6
人们已经习惯了将404解释为“页面未找到”,以至于当它出现在API的上下文中时,他们无法从逻辑上分离开来。 - The Muffin Man
3
这个东西已经“404”了,也就是说Thingyblob目前还不存在,未来也可能不会存在。对于http协议来说,它是否存在并不重要。当前它不存在,因此显示为“404”。如果它以后存在了,那需要通过从服务器向客户端推送一条消息来解决这个问题,例如:"Thingyblob:1234 可用"。然后再执行一次获取操作,就可以得到它的信息。 - 100r
1
虽然这是技术上正确的,但我们需要在响应主体或标头中返回其他信息,以便将其与“正常”的404响应区分开来,在这种情况下,我们不会尝试再次请求。我发现采用202方法更容易。 - alfoks
显示剩余2条评论

22
另一个选择: 503 - 服务不可用

5
根据W3C(万维网联盟)的说法,这不是您想要向客户端传达的信息(尽管在某种意义上意味着“请再来一次”):“由于服务器临时超载或正在维护,导致无法处理请求。这意味着这是一个暂时的状态,在一段时间后将会消除。如果已知延迟的长度,则可以在“重试-之后”标头中表示。如果未给出“重试-之后”标头,则客户端应该将响应处理为500响应。” - skalee
9
服务并未不可用,服务可用但处理尚未完成。因此,503 可能不是一个好选择。 - Ishtiaque Khan

21

由于您的资源尚未准备就绪,您可能知道它何时(大约)可用以及客户端可以重试请求的时间。这意味着您可能希望利用Retry-After header。该标头与503(服务不可用)一起有效,这意味着整个站点正在进行维护,并且3xx(重定向)响应。

在我看来,使用Retry-After标头的302(Found)将是最佳选择,但我不确定响应标头的位置字段是否可以等于请求URL。无论如何,这都是循环重定向。


3
即使允许使用,如果客户端没有实现对Retry-After头的支持,则重定向到相同页面的3xx重定向可能最终会导致503错误……(当然可以选择使用Retry-After头)。 - Ron Deijkers
1
Retry-After 也适用于 HTTP 429 "Too Many Requests",由 RFC 6585(2012年4月)添加。如果资源尚未准备好的原因是客户端给服务器的工作过多,则可能会使用此选项。 - Silas S. Brown

14

409冲突错误

意味着由于请求中存在冲突,例如多次更新中的编辑冲突,因此请求无法处理。[来源维基百科]

这可能是合适的。

如果无法通过返回数据满足请求,则不算成功。我认为202表示服务器已将请求排队,并将在稍后满足请求。但在您的情况下,请求现在是针对数据的,但已失败。如果稍后重试,那么就是不同的请求。

我认为您存在冲突.. 您需要数据.. 但正在被编辑/更新。如果Thingy1234已经存在并且之前成功下载过,但现在正在被编辑并且在编辑过程中不可用,那么这也是情况所在。


4
不确定为什么这个回答被投票否决了。对我来说,它似乎是正确的。根据RFC:“409(冲突)状态代码表示由于与目标资源的当前状态发生冲突而无法完成请求。该代码用于用户可能能够解决冲突并重新提交请求的情况。”您请求一个资源,但服务器无法返回该资源,因为服务器正在更新该资源 - 即由于资源的当前状态。客户端可以通过等待并重新提交来解决这个问题。 - Adam
4
我认为“用户可能能够解决冲突”中的暗示是,重新提交的某些方面将会有所不同,不仅仅是等待。 - Holistic Developer

-3

501 - 未实现

字面意思就是还没有实现的功能,但暗示着将来会有。

这里有一个5xx错误摘要的链接。


6
这个问题似乎是指该功能本身存在,但请求的项目不存在。 - Luke
@Luke 501在我的回答链接中的描述是:“...它缺乏满足请求的能力。通常这意味着将来会有可用性。” 这正好满足了OP的要求。无论数据是否存在于他的服务器或数据库中,最终结果是现在无法通过API访问。因此,API无法满足请求,但希望通过http代码暗示将来会提供可用性。 - Dan

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