This is my first SO question please be kind.
Every now and again when building an API you encounter a request which takes a while to process. A long API process can cause the request to timeout.
(In my case a PUT or a POST method which involves uploading to and communicating with a third party, eBay. This creates or updates a listing and returns the response info.)
To avoid timeouts I decided to send a response to the user with a URL that they can poll for the eventual results. (The idea was from SO searching, I used this method for returning the HTTP response while continuing to process and this idea for the design concept: POST/PUT to one address then GET at another.)
I want to have this ‘forked’ processing be optional for API requests so that it can be turned on or off in the future. That means the user of the API might just receive their desired result or might get a different URL from which to GET the result eventually. It seems that the HTTP response code is the best way to handle this. Return 200 when your result is coming back as expected and something else when the user should follow by a GET to a different URL a little while later.
So choosing the correct HTTP response code proved a little more subtle than I hoped (I thought I could just use a custom code, 314 for easy as pi). It seems like 3xx should be used since this is a redirection, but when I use 303 the browser handles the redirect immediately and still takes just as long actually (using POSTMAN in chrome). Using 307 isn’t appropriate as I want the next request to be a GET and not a PUT or POST. A custom 3xx was still redirected automatically by the browser. When I use ‘305 Use Proxy’ everything works. The user of the API gets a response immediately and they can choose to handle it as they see fit.
So here is the question: Is it safe to rely on this browser behavior to 305 Use Proxy (allowing the user to handle the next call)? If not what is the best alternative code?
The responses to this question imply that 305 is not implemented and might be deprecated.
The W3C paragraph for 305 says
The requested resource MUST be accessed through the proxy given by the Location field. The Location field gives the URI of the proxy. The recipient is expected to repeat this single request via the proxy. 305 responses MUST only be generated by origin servers.
I took that to mean that the proper behavior is that the recipient is entrusted to repeat the request which is what I want.
This response says “I hope you’re not trying to generate a 305 response.”
I was happy that 305 worked this way, so I can either give you your answer or let you decide when to poll some other URL for your answer later when it might be ready. If I can rely on that behavior in the near future then it means not having to mess with websockets or queueing long tasks or gateway timeouts. I’m worried that browsers do what I want out of coincidence rather than design, and maybe in the future 305 is dropped or browsers do the redirection automatically like the other 3xxs. I would prefer not to use 4xx since it’s not an error, but I could be talked into it.
2
Answers
From the look of it 305 doesn’t correspond to what you are trying to do. Repeating a request through a proxy is different from requesting a resource from a different location, or from polling a URL.
Perhaps just return a JSON object with a link to the URL that needs to be polled and document the behavior. Nobody writes API clients that magically handles HTTP codes anyway (besides the obvious 404, 200, etc.), so you always need to document it if you need something more complex than plain redirections.
This is exactly the use case for “202 Accepted” status code:
The response can contain Location header to indicate where the client needs to query for the status of the request.
As far as I know, no browsers implements anything special with 202 Accepted, so you’ll need to implement the handling of 202 Accepted in the client side yourself.
One possible implementation is that the URI in Location header would be the URI that the resource you’re trying to create will end up in, and it would return 404 on a GET request until the processing is finished.
Another more sophisticated implementation is that the URI in Location header would be the URI for the progress resource for the asynchronous request, and it would return a 200 OK with the progress status of the request, and when the processing is finished, the resource will return a 201 Created with the final Location of the created resource.