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

时间:2011-02-22 14:27:01

标签: 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处理数据的任何意见或经验。

4 个答案:

答案 0 :(得分:36)

我认为您的解决方案很好,Http status 202是在此特定情况下使用的proper response,表示请求已被接受处理,但处理尚未完成

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

正如您所说,202 response应返回Location header,指定客户端用于监控其先前请求状态的网址。
调用此检查我的进程状态 URL,而不是在进程挂起的情况下返回202,我会返回:

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

答案 1 :(得分:25)

将我的两分钱加到旧问题上。我的想法类似于systempuntoout和Avi Flax的建议。

我同意HTTP 202响应适用于初始请求,并通过Location标头重定向到其他资源。

我认为Location网址应该包含您引用的令牌,以符合Location重定向的常见期望。例如Location: /queue?token={unique_token}Location: /task/{unique_token}

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

但是,我认为在创建新实体时“检查状态”应该返回HTTP 303See Other)响应,并在新实体生成后使用Location标头创建。这比发送HTTP 201更合适,因为由于刚刚执行GET请求来检查状态而没有创建任何内容。

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

答案 2 :(得分:6)

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

从客户的角度来看

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

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

从服务角度

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

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

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

现在,我开始看到与上述反应略有不同的地方。

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

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

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

再次从客户的角度来看

当客户端获得其初始POST的响应时,它会获得"位置"并使用GET(再次,不是POST)使用该URL向服务发出请求。该服务通常会响应这些值:

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

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

此外,服务开发人员可以使服务过期并在短时间内删除错误资源。

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

答案 3 :(得分:1)

FWIW,Microsoft Flow使用这样的模式。
第一次调用返回202 w / Location标头。 跟进电话返回: 1.如果仍在处理 - > 202 w / a位置标题。 loc头可以是不同的,这提供了一种在调用之间传递状态的方法(并且可能使服务器无状态!)。 2.如果完成 - > 200.

详细信息:https://github.com/jeffhollan/LogicAppsAsyncResponseSample