167

I'm developing a RESTful API in which http://server/thingyapi/thingyblob/1234 returns the file (aka "blob") associated with thingy #1234 to download. But it may be that the request is made at a time the file does not exist in the server but most definitely will be available at a later time. There's a batch process in the server that generates all the blobs for all the thingies. Thingy 1234 already exists and its data, other than the blob, is already available. The server hasn't got to generating thingy 1234's blob yet.

I don't want to return 404; that's for thingies that do not exist. This is a thingy that exists, but its blob hasn't been generated yet. Kinda like a YouTube video that's "processing." I don't think redirection codes would be proper either; there's no "other" URL to try.

What's the correct HTTP status code to return in such a case?

Toby Speight
  • 23,550
  • 47
  • 57
  • 84
JCCyC
  • 14,557
  • 11
  • 41
  • 73
  • 3
    [Somewhat related](http://stackoverflow.com/questions/7730199/best-practice-for-implementing-long-running-searches-with-rest/7730452#7730452) – Rob Hruska Mar 20 '12 at 21:04
  • 7
    First, if thingy 1234 does not yet have any GET-able representation, in what sense does it exist as a resource (from the client's perspective)? The fact that, internal to the server there is a queued job to create 1234, doesn't seem to imply that resource 1234 exists. Second, where did the client get the URI .../thingyblob/1234? The server probably shouldn't have provided that URI to the client until the resource was actually GET-able. – Andy Dennie Mar 21 '12 at 14:16
  • 1
    A thingy has other properties that are worth getting other than the blob. It's only the blob that takes time to generate. Client gets those by, for example, http://server/thingyapi/thingy/1234 – JCCyC Mar 21 '12 at 16:29
  • possible duplicate of [Is it wrong to return 202 "Accepted" in response to HTTP GET?](http://stackoverflow.com/questions/4099869/is-it-wrong-to-return-202-accepted-in-response-to-http-get) – Gili Dec 11 '12 at 22:57
  • 10
    The HTTP standard provides guidance about which status codes to use for which situations. This question is therefore not really _primarily opinion-based_. – Raedwald Mar 15 '16 at 16:24
  • 2
    How about `204` "No Content"? Is indicates that the server has successfully processed the request and is not returning any content [at this time]. – Timo Jun 26 '18 at 08:33
  • 1
    How is this opinion-based? There's a very clear set of codes that can be used. – Zimano Jan 30 '20 at 12:50

8 Answers8

83

I suggest 202 - Accepted. From the documentation:

The request has been accepted for processing, but the processing has not been completed. [...] Its purpose is to allow a server to accept a request for some other process (perhaps a batch-oriented process that is only run once per day)

matsev
  • 26,664
  • 10
  • 102
  • 138
  • 80
    -1: This would make sense for the request which initiates the process that eventually creates "thingy #1234", but not for the GET request issued afterwards for "thingy #1234" itself. In particular, a 202 suggests that as a result of the GET request, the service will send the data for "thingy #1234" at a later point in time. This is simply not correct. – Sam Harwell Oct 14 '14 at 22:10
  • The documentation clearly states: "The request might or might not eventually be acted upon", so there is no obligation for a GET to send data later if 202 is reported. – Remy Lebeau Oct 15 '14 at 14:34
  • 8
    It also says: "The entity returned with this response SHOULD include an indication of the request's current status and either a pointer to a status monitor or some estimate of when the user can expect the request to be fulfilled.", so this would be a good way to let the client know that the blob is not ready yet, and a way to find out when it is ready. – Remy Lebeau Oct 15 '14 at 14:37
  • 4
    I would argue that "accepted for processing" indicates that you're saving the request to be acted on later. If it's just being ignored, you should return a 4xx or 5xx code to indicate to the client that they might want to try again. – Luke Oct 20 '16 at 15:17
  • 4
    102 (processing) seems also a reasonable choice sometimes even though it is in webdav spec. – akostadinov Dec 02 '16 at 10:19
  • 3
    Can't disagree more with this answer. The server is not returning anything, or planning to (not doing any processing because of this request - which it anyway should not for a GET). As such, the resource is in some fashion not available to the client. This should be treated as an error so no 2XX code is appropriate. Something in the 4XX or 5XX space. The request has *not* _"been accepted for processing"_, the request is in practice being discarded – Adam Oct 21 '18 at 14:15
  • The anser by @Raedwald is a much better approach – Juan Fuentes Jul 25 '19 at 15:41
73

The "problem", such as it is, is on the server side: the client has made a well formed request, but the server can not satisfy it. So I'm inclined to a "Server Error", 5xx status code.

Quoth RFC 7231 (the current HTTP standard, emphasis added):

The 5xx (Server Error) class of status code indicates that the server is aware that it has erred or is incapable of performing the requested method. Except when responding to a HEAD request, the server SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition.

Note

  • "erred or is incapable of performing the request": despite their title of "Server Error", they are not just for server errors.
  • "temporary or permanent": these codes are suitable for temporarily unavailable resources, like yours.

Of the available codes, I'd say 503, "Service Unavailable" was the best fit:

The 503 (Service Unavailable) status code indicates that the server is currently unable to handle the request due to a temporary overload or scheduled maintenance, which will likely be alleviated after some delay. The server MAY send a Retry-After header field... to suggest an appropriate amount of time for the client to wait before retrying the request.

Note:

  • "likely be alleviated after some delay": true for your case.
  • "temporary overload": not pedantically true for your case. But, it could be argued, were your server much faster, the batch processing would have already been done when the client made the request, so it is a kind of "overload": the client is asking for resources faster than the server can make them available.
  • Retrying is suitable for your service, so your reply ought to include a Retry-After value. You could provide as the value the estimated completion time of the next execution of the batch process, or the execution interval of the batch process.

Defining your own 5xx status code (591, for example), although permitted, would have the wrong semantics:

a client MUST understand the class of any status code, as indicated by the first digit, and treat an unrecognized status code as being equivalent to the x00 status code of that class

Clients would treat your own status code as 500, "Internal Server Error", which would not be right.

Raedwald
  • 40,290
  • 35
  • 127
  • 207
  • 2
    I fail to see how it's better than 202: http://benramsey.com/blog/2008/04/http-status-201-created-vs-202-accepted/ – JCCyC Sep 06 '12 at 22:24
  • 4
    @JCCyC your blog makes a good case for returning a 202 in response to a request to create something (a POST or PUT). The question seems to be asking about what to return for a GET. – Raedwald Sep 06 '12 at 22:49
  • @JCCyC it could be seen as a different shade of not-ready-ness: imagine an ajax to that ressource, do you prefer 202 as a success status or 503 as an the error status? so you can see which meaning you prefer implicitly in the context of your app's reaction to the response – rloth Jul 27 '16 at 11:26
  • also i like the practical aspect of "Retry-After" that goes well with something being "not ready" – rloth Jul 27 '16 at 11:29
  • 3
    NB: "Retry-After" can also go with **`307 - TEMPORARY REDIRECT`** which is good if you want to force client side to wait elsewhere while your ressource is being "made ready" – rloth Jul 27 '16 at 11:36
  • 2
    This is not a problem with the server. 5xx codes should not be used. The use case is an expected and valid state of the system. Partially generated records are not the same as a partially functional server. There is no problem with the client either. They are asking for a valid resource that will exist at some point. 4xx codes should not be used. The server's response should be "OK, but I'm still working on it" (202 Accepted). – Jared Deckard Mar 07 '19 at 17:15
35

I think that 423 - Locked can be used for this purpose:

The 423 (Locked) status code means the source or destination resource of a method is locked. This response SHOULD contain an appropriate precondition or postcondition code, such as 'lock-token-submitted' or 'no-conflicting-lock'.

Fernando Ortega
  • 562
  • 5
  • 15
  • 1
    Excellent answer! I wonder why it doesn't have more upvotes. – lex82 Jun 03 '16 at 08:56
  • 13
    Perhaps because it is a WebDAV HTTP code ? – Stephan L Aug 18 '16 at 14:49
  • 1
    From akka-http there is StatusCode RetryWith = reg(c(449)("Retry With", "The request should be retried after doing the appropriate action.")) where the action would be wait and retry – ozma Mar 29 '18 at 07:37
  • 2
    In many ways I agree with this. I have a similar situation (in my case searching from an index which may not yet be populated). Semantically, I think this is correct. However, the RFC for 423 states _"This response SHOULD contain an appropriate precondition or postcondition code, such as 'lock-token-submitted' or 'no-conflicting-lock'."_ Not sure how to apply that here. And personally I'd go with 409 Conflict, but that's been downvoted without comments - not sure why? – Adam Oct 21 '18 at 14:11
25

I don't want to return 404; that's for thingies that do not exist.

The URL doesn't correspond to a request for a thingy.

http://server/thingyapi/thingyblob/1234

The client is requesting a thingyblob, which doesn't exist. If it existed, you would give it to them.

404.

funroll
  • 31,708
  • 7
  • 49
  • 56
  • 1
    I'm glad someone said this! I can't believe there are so many people that think `503` is an appropriate response. Not to mention some of the other strange suggestions. – Jason Desrosiers Apr 29 '15 at 06:36
  • Although I agree that a 404 is the most appropriate response here, it doesn't answer the OP's question how to indicate when the thingy is available :-). I think the Retry-After field seems the best candidate but it can only officially be used for 503 and 3xx codes. @Jason: I think that explains some of the strange suggestions. – Ron Deijkers Aug 14 '15 at 13:03
  • I think this is the best answer. You are allowed to return a body in a 404 response. The body could indicate that the thingy will be available at a later date. Or use Retry-After header as well. The standard needs to be stretched a bit here because it doesn't cover this case nicely. – WW. Oct 07 '15 at 00:30
  • 4
    People have become too acclimated to 404 meaning page not found that they can't logically dissociate that when in the context of an API. – The Muffin Man May 07 '17 at 20:15
  • 1
    This is sooooo 404. Thingyblob does not exists yet, or ever.. For http its irelevant if it will ever be available. At the moment it does not exist, and its 404. When it will be available is another problem, which can be solved by pushing a mesage from server to client sayin thingyblob: 1234 available. Perform a get again and voila.. – 100r May 21 '19 at 15:01
  • While this is techical correct, we need to return additional info in the response body or headers, to somehow differentiate it from "normal" 404 responses, in which we will not try again later. I found it easier to go with the 202 approach. – alfoks Dec 11 '20 at 14:19
22

Another option: 503 - Service Unavailable.

Brian Kelly
  • 17,943
  • 4
  • 46
  • 54
  • 5
    [According to W3C](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) it's not what you want to say to client (although it means "come again" in some manner): "The server is currently unable to handle the request due to a temporary overloading or maintenance of the server. The implication is that this is a temporary condition which will be alleviated after some delay. If known, the length of the delay MAY be indicated in a Retry-After header. If no Retry-After is given, the client SHOULD handle the response as it would for a 500 response." – skalee Jan 21 '13 at 05:13
  • 5
    Service is not unavailable, service is available but processing is not complete. So 503 is probably not a good idea. – Ishtiaque Khan Mar 11 '18 at 17:23
18

Since your resource is not ready, you probably know when (approximately) it will be available and when client may retry his request. This means you might want to utilize Retry-After header. This header is valid with 503 (Service Unavailable), which means whole site is down for maintenance, and 3xx (Redirection) responses.

In my opinion 302 (Found) with Retry-After header would be the best option, but I am not sure if Location field of response header can be equal to request url. It's circular redirect, anyway.

skalee
  • 10,976
  • 6
  • 47
  • 54
  • 3
    Even if it is allowed, if the client hasn't implemented support for the Retry-After header then a 3xx Redirection to the same page might eventually end in a 503... (optionally with a Retry-After header of course) – Ron Deijkers Aug 14 '15 at 13:19
  • 1
    Retry-After is also valid with HTTP 429 "Too Many Requests", added by RFC 6585 (April 2012). This might be appropriate if the reason for the resource not yet being ready is the client has been giving the server too much work to do. – Silas S. Brown Oct 05 '17 at 09:29
8

409 Conflict

Indicates that the request could not be processed because of conflict in the request, such as an edit conflict in the case of multiple updates. [Source Wikipedia.]

This could be appropriate.

If you cant fulfill the request by returning the data - then its not a success. I think 202 suggests the server has queued the request and it will fulfill the request later. But in your case, the request is for data now and has failed. If you retry later it is a different request.

I think you have a conflict.. you want the data.. but its being edited / updated. This would also be the case if Thingy1234 already existed and had been successfully downloaded before, but now was in the process of being edited was was unavailable whilst the edit was taking place.

J Moore
  • 111
  • 1
  • 1
  • 3
    Not sure why this got voted down. Seems like the right answer to me. From the RFC: _"The 409 (Conflict) status code indicates that the request could not be completed due to a conflict with the current state of the target resource. This code is used in situations where the user might be able to resolve the conflict and resubmit the request._" You asked for a resource which the server cannot return because the server is in the process of updating that resource - i.e. due to the current state of the resource. The client can resolve this by waiting and resubmitting – Adam Oct 21 '18 at 14:10
  • 1
    @Adam I think the implication in "user might be able to resolve the conflict" is that something about the resubmission would be different, other than just waiting. – Holistic Developer Apr 22 '20 at 20:29
3

501 - Not Implemented

Exactly like how it sounds. A feature that is not yet implemented, but implies future availability.

Here is a link to a summary of 5xx errors.

Bruce P
  • 17,554
  • 7
  • 59
  • 69
Dan
  • 464
  • 4
  • 16
  • 4
    For this question it sounds like the feature itself exists, but the item being requested does not. – Luke Oct 20 '16 at 15:19
  • @Luke 501's description from the link in my answer, '...it lacks the ability to fulfill the request. Usually this implies future availability'. This is fulfills exactly what the OP was asking for. Regardless of whether or not the data is there on his servers or DB. The ultimate result is that it is not accessible via the API for now. Therefore the API can't fulfill the request, but would like to imply that it will be available in the future via the http code. – Dan Oct 20 '16 at 18:00