使用http状态202进行asynchronous操作
我正在编写一个REST API来接受用户提供的数据。 我想保持所有操作完全asynchronous,这包括PUT,POST,DELETE甚至GET请求。 我的想法是接收请求,处理它足以确保它是一个有效的请求,然后传递一个HTTP 202接受的响应连同数据将最终可用的URL和令牌,以便后续的请求可以匹配处理的数据。 如果请求无效,那么我将发送一个HTTP 400。
然后客户将负责检查我在将来某个时间提供给他们的url,并传递令牌。 如果数据可用,则返回正常的200或201,但是如果我仍在处理请求,则会发送另一个202,指示处理尚未完成。 如果处理数据出错,我会根据需要发送4xx或5xx状态。
我想这样做的原因是我可以将所有有效的请求转储到请求池中,并让工作人员从队列中拉出来,并在请求可用时处理请求。 由于我不知道游泳池的大小或可用的工作人员数量,我不能确定我是否可以快速获得足够的要求来满足Google App Engine的30秒限制。
我的问题是:我是通过这种方式处理请求歪曲REST? 例如,浏览器似乎需要立即回应请求。 对于我的HTML页面,我计划用结构化页面进行响应,然后使用AJAX处理数据请求。
我最感兴趣的是以这种方式使用REST处理数据的任何意见或经验。
我认为你的解决scheme是好的,在这种特定的情况下, Http status 202
是正确的响应 ,表明请求已被接受处理,但是处理还没有完成 。
我会稍微改变你的工作stream程中的后续请求的Http status
。
正如你所说的, 202 response
应该返回一个Location header
指定客户端应该用来监视其先前请求状态的URL。
调用这个Check-the-status-of-my-process URL,而不是在进程挂起的情况下返回202,我将返回:
-
200 OK
当请求的进程仍然未决时。 响应应描述该过程的待定状态。 -
201 Created
处理完成时201 Created
。 在GET / PUT / POST的情况下的响应应该包含所请求/创build/更新的资源的位置。
把我的两分钱添加到一个旧的问题。 我的想法与systempuntoout和Avi Flax的build议类似。
我同意HTTP 202
响应适用于通过Location
标题redirect到另一个资源的初始请求。
我认为Location
url应该包含您引用的令牌,以符合常见的Location
redirect期望。 例如Location: /queue?token={unique_token}
或Location: /task/{unique_token}
。
我还认为用于检查进程状态的资源应该在“检查状态”的操作成功时返回HTTP 200
响应(而不是HTTP 202
因为这意味着当前请求被“接受”)。
但是,我认为当创build新实体时,“检查状态”应该在新实体创build后返回一个带有Location
头的HTTP 303
( 请参阅其他 )响应。 这比发送HTTP 201
更合适,因为没有任何事情是由于刚才执行的GET
请求来检查状态而创build的。
我也认为用于检查状态的资源应该适当地返回错误代码。 每当“检查状态”成功执行,都应该返回一个合适的成功代码。 可以在应用程序级别处理错误(通过检查响应主体)。
这是一个非常古老的问题,但我想提出一个稍微不同的观点,我不认为这是正确的,只是我的观点。
从客户的angular度来看
我们从最初的HTTP请求开始。 首先,请求应该是POST。 您正在向服务器发送消息以创build资源。 GET和PUT在这种情况下无效,因为:
- GET在此上下文中无效,因为GET旨在获取特定位置的资源
- PUT无效,因为您没有创build请求,而是要求服务器创build请求。
从服务的angular度来看
所以,现在你正在发送一个POST到服务器来处理一个请求。 服务器有3个可能的返回值(不包括4xx和5xx错误):
- “201 Created”表示服务获得了请求,并能够立即或在可接受的时间内对其进行处理。 这个时间段完全取决于服务devise。 由服务开发人员来定义这一点。
- “202 Accepted”表示服务已经得到请求并正在处理它。 当服务知道某些事情需要一段时间时使用这个。 另一个angular度是,如果服务依赖于任何其他的无法确定结果的asynchronous操作,那么它应该返回“202 Accepted”响应。 最后,一些服务devise者可能总是返回“202 Accepted”,不pipe它能够多快地完成。
- 在某些情况下,你会得到一个“302find”。 这通常是服务可以将请求标识为生成已经存在的资源(并且仍然有效且不处于错误状态)并且重用现有资源是可接受的。 并不是所有的服务都是这样工作的:发表评论到一个线程应该总是创build一个新的资源。 其他服务:做一系列的标准,以获得医生列表产生相同的医生名单。 如果这个信息可以被重复使用,那么重用它。
- 通过所有这些响应,“位置”HTTP标题被返回到包含可以find资源的位置的客户端。 这是很重要的,有些人倾向于分歧的方式,你将会看到。 如果资源可以与其他请求重复使用,那么“位置”应该确实以相同的请求始终生成相同的URL的方式生成。 这提供了大量的caching和重用。
当服务成功完成请求时,它将在返回给客户端的位置创build资源。
现在,我开始看到与上面的反应有些不同的地方。
如果服务未能完成请求,它应该仍然在返回给客户端的位置创build一个资源。 这个资源应该指出失败的原因。 有一个资源提供失败信息比试图使用HTTP协议更灵活。
如果服务在完成之前得到了这个资源的请求,它应该返回一个“404 Not Found”。 我认为它应该是一个“404 Not Found”的原因是因为它确实不存在。 HTTP规范并没有说“404 Not Found”只能用于资源永远不会存在的地方,只是它现在不存在。 我认为这种对asynchronous轮询stream程的响应是完全正确的。
还有一种情况是资源何时应该在一个固定的时间。 例如,它可能是基于每晚刷新的源的数据。 在这些情况下应该发生的事情是资源应该被移除,但是应该向可以返回“410 Gone”状态码的服务提供一个指示符。 这基本上是告诉客户,资源在这里,但不再可用(即:可能已经过期)。 客户端的典型操作是重新提交请求。
再次从客户的angular度来看
当客户端获得初始POST的响应时,它获取“Location”并使用GET(再次,不是POST)使用该URL向服务发出请求。 该服务通常会回应这些值:
- “200 OK”表示请求完成。 请求的结果在内容主体中返回,以Accept HTTP标头定义的格式提供内容。
- “404 Not Found”会告诉客户端,请求还没有完成,资源还没有到,在这种情况下,基本上应该稍后再试。
- 如果客户在很长一段时间之后尝试获取资源,并且现在不在,那么将返回“410 Gone”。 在这种情况下,它应该简单地重新提交原始查询
有一点需要指出的是,返回的资源通常是可以定义成功和失败响应的格式。 客户应该能够从这个资源确定是否有错误,是什么,并能够作出相应的回应。
此外,服务开发人员可能会使服务在短时间内过期并删除错误资源。
所以这是我对这个问题的想法。 这个晚会已经很晚了,但希望未来的读者可能会看到一个常见问题稍有不同的观点。
FWIW,Microsoft Flow使用这样的模式。
首先呼叫返回202瓦特/位置标题。 后续调用返回:1.如果仍在处理 – > 202瓦特/位置标题。 loc头可以不同,它提供了一种在调用之间传递状态的方法(并可能使服务器无状态!)。 2.如果完成 – > 200。
详情请参阅: https : //github.com/jeffhollan/LogicAppsAsyncResponseSample