使用http状态202进行异步操作

Jam*_*ett 59 rest

我正在为接受用户贡献数据的服务编写REST API.我想保持所有操作完全异步,这包括PUT,POST,DELETE甚至GET请求.我的想法是接收请求,处理它以确保它是一个有效的请求,然后传递HTTP 202接受的响应以及数据最终可用的URL和令牌,以便后续请求可以与处理的数据匹配.如果请求无效,那么我将发送HTTP 400.

然后,客户将负责检查我在将来的某个时间提供的URL,并传递令牌.如果数据可用,我返回正常的200或201,但如果我仍在处理请求,我将发送另一个202,表明处理尚未完成.如果处理数据有错误,我会根据需要发送4xx或5xx状态.

我想这样做的原因是我可以将所有有效请求转储到请求池中,并让工作人员从队列中提取并处理请求,因为它们可用.由于我不知道池的大小或可用的工作人员数量,因此无法确定我能够以足够快的速度获得请求以满足Google App Engine的30秒限制.

我的问题是:我是否通过以这种方式处理请求来歪曲REST?例如,浏览器似乎需要立即响应请求.对于我的HTML页面,我计划使用结构化页面进行响应,然后使用AJAX处理数据请求.

我最感兴趣的是以这种方式使用REST处理数据的任何意见或经验.

sys*_*out 41

我认为您的解决方案很好,这Http status 202是在这种特定情况下使用的正确响应,表明请求已被接受处理,但处理尚未完成.

我在您的工作流程中稍微改变Http status的是后续请求.

正如您所说,202 response应该返回一个Location header指定客户端应该用来监视其先前请求状态的URL.
调用这个Check-the-my-process- URL,而不是在进程挂起的情况下返回202,我会返回:

  1. 200 OK当请求的进程仍处于待处理状态时.响应应描述该过程的待定状态.
  2. 201 Created处理完成后.GET/PUT/POST情况下的响应应包含所请求/创建/更新资源的位置.

  • 我同意这一点,但我不认为"201"或"202"对后续请求有意义.状态代码用于指示请求/响应的状态 - _not_资源.在后续请求中坚持使用"200",并使用该表示来表示资源的状态. (15认同)

Tre*_*ner 27

把我的两分钱加到一个老问题上.我的想法类似于systempuntoout和Avi Flax的建议.

我同意HTTP 202响应适用于初始请求,并通过Location标头重定向到另一个资源.

我认为LocationURL应该包含您引用的令牌以符合Location重定向的共同期望.例如Location: /queue?token={unique_token}Location: /task/{unique_token}.

我还认为用于检查进程状态的资源应该HTTP 200在"检查状态"的操作成功时返回响应(不是HTTP 202因为这意味着当前请求被"接受").

但是,我认为在创建新实体时,"检查​​状态"应该在创建新实体时返回一个HTTP 303(请参阅其他)响应,并带有Location标题.这比发送a更合适,HTTP 201因为GET刚刚执行检查状态的请求没有创建任何内容.

我还认为用于检查状态的资源应该适当地返回错误代码.只要成功执行"检查状态",就应返回适当的成功代码.可以在应用程序级别处理错误(通过检查响应正文).


Din*_*one 7

这是一个非常古老的问题,但我想提出一个略有不同的观点,我并不认为这是正确的,只是我的看法.

从客户的角度来看

让我们从最初的HTTP请求开始.首先,请求应该是POST.您正在向服务器发送消息以创建资源.在这种情况下,GET和PUT无效,因为:

  • GET在此上下文中无效,因为GET旨在获取特定位置的资源
  • PUT无效是因为您没有创建请求,而是要求服务器创建请求.

从服务的角度来看

所以现在您要向服务器发送POST来处理请求.服务器实际上有3个可能的返回值(不包括4xx和5xx错误):

  • "201 Created"表示服务获得了请求,并且能够立即处理,或者在可接受的时间段内处理.这段时间完全取决于服务设计.由服务开发人员来定义它.
  • "202 Accepted"表示该服务获得了请求并正在处理它.当服务知道某些事情需要一段时间时,就会使用此方法.另一个观点是,如果服务依赖于任何其他无法确定结果的异步操作,那么它应该返回"202 Accepted"响应.最后,一些服务设计人员可能总是返回"202 Accepted",无论其执行速度有多快.
  • 在某些情况下,你会得到一个"302 Found".这通常是当服务可以将请求标识为生成已经存在的资源(并且仍然有效且不处于错误状态)并且可以接受重用现有资源时.并非所有服务都这样工作:向线程发布评论应始终创建新资源.其他服务:发布一组标准,以获得医生列表产生相同的医生名单.如果可以重用此信息,则重复使用它.
  • 通过所有这些响应,"位置"HTTP标头将返回到包含可以找到资源的位置的客户端.这很重要,有些人倾向于分道扬铛,你将在后面看到.如果资源可以与其他请求一起使用,那么"位置"应该以相同请求始终生成相同URL的方式生成.这提供了大量的缓存和重用.

当服务成功完成请求后,它将在返回给客户端的位置创建资源.

现在,我开始看到与上面的响应略有不同的地方.

如果服务无法完成请求,它仍应在返回给客户端的位置创建资源.该资源应指出失败的原因.使资源提供故障信息比尝试将其变为HTTP协议更加灵活.

如果服务在完成之前获得对此资源的请求,则应返回"404 Not Found".我认为它应该是"404 Not Found"的原因是因为它确实不存在.HTTP规范并未说"404 Not Found"只能用于资源永远不存在的情况,只是它现在不存在.在我看来,这种对异步轮询流的响应是完全正确的.

还有一种情况是资源应该只存在一段固定的时间.例如,它可以是基于每晚刷新的源的数据.在这些情况下应该发生的情况是应该删除资源,但是应该向服务提供一个指示器,它可以知道返回"410 Gone"状态代码.这基本上告诉客户端资源在这里,但不再可用(即:可能已经过期).客户端的典型操作是重新提交请求.

从客户的角度来看

当客户端获得其初始POST的响应时,它获取"位置"并使用GET使用该URL向服务发出请求(同样,不是POST).该服务通常会响应以下值:

  • "200 OK"表示请求已完成.请求的结果在内容正文中返回,以Accept HTTP标头定义的格式提供内容.
  • "404 Not Found"会告诉客户端请求尚未完成,资源尚未完成,在这种情况下,它基本上应该稍后重试.
  • 如果客户可能在很长一段时间后尝试获取资源并且不再存在,则会返回"410 Gone".在这种情况下,它应该只是重新提交原始查询

需要指出的一点是,返回的资源通常采用可定义成功和失败响应的格式.客户端应该能够从该资源确定是否存在错误,错误是什么,并且能够做出相应的响应.

此外,服务开发者可以使服务过期并在短时间后删除错误资源.

这就是我对这个问题的看法.派对已经很晚了,但希望未来的读者可能会看到一个与常见问题略有不同的观点.

  • 404的问题在于它是可缓存的.(见http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-25#section-6.1).重试404直到它成功可能不是一个好的模式使用,似乎非常不标准.4xx错误特别是客户端错误.4xx错误意味着客户端犯了错误或未能传递访问资源所需的一些必要信息.在正常使用中,获取解析为404的Location标头是一个错误.(例如竞争条件或数据库一致性问题.) (3认同)
  • 好点.Cacheable问题可以通过缓存控制HTTP标头解决.关于第二点,这是一个好点.从技术上讲,这不是对404的错误使用,但你确实提出了一个有效的问题. (2认同)
  • 您可以考虑使用 Content-Location 标头来检索操作的状态。否则我同意迪诺的观点。内容位置的灵感可以在 Microsoft Azure 上找到:https://learn.microsoft.com/en-us/rest/api/hdinsight/asynchronous-operations--202-accepted-and-location-header- (2认同)