36

What is the appropriate way of giving an estimate for request completion when the server returns a 202 - Accepted status code for asynchronous requests?

From the HTTP spec (italics added by me):

202 Accepted

The request has been accepted for processing, but the processing has not been completed. [...]

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.

Here are some of thoughts:

  • I have glanced at the max-age directive, but using it would be abusing Cache-Control?
  • Return the expected wait time in the response body?
  • Add an application specific X- response header, but the X-headers was deprecated in RFC 6648?
  • Add a (non X-) specific response header? If so, how should it be named? The SO question Custom HTTP headers : naming conventions gave some ideas, but after the deprecation it only answers how HTTP headers are formatted, not how they should be named.
  • Other suggestions?
Community
  • 1
  • 1
matsev
  • 32,104
  • 16
  • 121
  • 156

3 Answers3

21

Definitely do not abuse existing HTTP headers for this. Since it's your own server, you get to define what the response looks like. You can (and should) pick whatever response works best for the intended recipient of this information and return the actual information in the response body.

For example, if you are only interested in displaying a human-readable message then you could return text/plain saying "Your request is likely to be processed in the next 30 minutes.".

At the other end of the spectrum, you might want to go all the REST way and return application/json, perhaps formatted like this (I totally made this up on the spot):

{
  "status": "pending",
  "completion": {
    "estimate": "Thu Sep 08 2011 12:00:00 GMT-0400",
    "rejected-after": "Fri Sep 09 2011 12:00:00 GMT-0400",
  },
  "tracking": {
    "url": "http://server/status?id=myUniqueId"
  }
}
Jon
  • 428,835
  • 81
  • 738
  • 806
14

You can use the Location header to specify the URL of the status monitor. Things like current status and estimate can either go in custom headers (which noone but your own software would use), or in the response body (which a web browser would display to a user, at least).

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thanks, I forgot about the `Location` header. Most likely, we will use a custom response body. – matsev Feb 14 '13 at 07:42
  • As it happens, one actually can't use the `Location` header with a HTTP 202 in PHP, because it enforces special semantics per RFC 2616, cf. http://php.net/manual/en/function.header.php "The second special case is the "Location:" header. Not only does it send this header back to the browser, but it also returns a REDIRECT (302) status code to the browser unless the 201 or a 3xx status code has already been set." – Josip Rodin May 03 '17 at 13:33
  • @JosipRodin RFC 2616 does not restrict `Location` from being used in 202 (or any other response), it merely defines what `Location` refers to in case of 201/3xx. So that is a PHP semantic (or bug, depending on how you look at it), not an HTTP semantic. – Remy Lebeau May 03 '17 at 14:56
  • @RemyLebeau tell that to PHP developers... here is the previous attempt to argue this point: https://bugs.php.net/bug.php?id=70273 and here's my recent request just to get it to tell people what it's doing: https://bugs.php.net/bug.php?id=74535 – Josip Rodin May 03 '17 at 18:57
  • @JosipRodin: "*one actually can't use the `Location` header with a HTTP 202 in PHP*" - the comment on https://bugs.php.net/bug.php?id=70273 from jeff at 2015-08-17 16:35 UTC shows several ways how to accomplish this in PHP. – Remy Lebeau May 03 '17 at 19:01
  • @RemyLebeau unfortunately it's pretty kludgy, as evidenced by numerous people complaining, e.g. http://stackoverflow.com/questions/26199228/is-the-use-of-location-header-in-http-202-response-rfc-compliant or http://stackoverflow.com/questions/25379247/header-in-php-overrides-the-http-response-code – Josip Rodin May 03 '17 at 19:10
  • @JosipRodin: "*its pretty kludgy*" - replacing `header('Location: ...')` with `header('Location: ...', true, 202)` is hardly a kludge. – Remy Lebeau May 03 '17 at 19:30
  • @RemyLebeau it is if you expected your `header('HTTP/1.1 202 Accepted')` not to have been trampled over, depending on ordering (!) – Josip Rodin May 04 '17 at 10:18
6

Although not explicitly mentioned specifically for the 202 - Accepted response code, the Retry-After header seems to be a suitable option. From the documentation:

The Retry-After response-header field can be used [...] to indicate how long the service is expected to be unavailable to the requesting client.

matsev
  • 32,104
  • 16
  • 121
  • 156
  • 1
    Given that the value is supposed to be "integer number of seconds (in decimal)", if we want a better resolution, would an `X-Retry-After` header with values in e.g. milliseconds be more appropriate instead? – Josip Rodin Nov 09 '16 at 16:39
  • @JosipRodin I suggest using `Retry-After: 0` instead of inventing a custom header because by the time the client gets the response a few milliseconds would have passed anyway and they can retry right away. In the case of an async operation, `Retry-After: 0` seems to say "the result isn't ready yet, but feel free to ask again (whenever you wish)." – Gili Apr 19 '17 at 04:56
  • @Gili but what if I don't want them to ask whenever they wish? For example, if the bulk of the clients are 150ms away, that's 6 requests per second, where I may have had the idea of having only 2 requests per second. – Josip Rodin Apr 19 '17 at 08:39
  • 1
    @JosipRodin This header is nothing more than a suggestion to the client. Clients can (and do) ignore it. This header is the server's way of saying: "You can repeat the request sooner if you wish, but I don't think the response will change for the next X seconds". Clients will do what suits them best so you'll never get the level of control you seem to be after. – Gili Apr 19 '17 at 19:20
  • @Gili that is orthogonal - it still makes sense to be able to communicate reasonable limits, in order to be able to provision resources in a reasonably predictable manner and to be able to better explain to abusive users exactly why they were rate-limited and/or blocked. – Josip Rodin Apr 22 '17 at 13:16
  • @JosipRodin You'll need to use a different mechanism for communicating rate limits, as `Retry-After` is not meant for that. I think `Retry-After` is legitimate for informing banned users of when they may retry, but I fail to see the need for sub-second precision in that case. Typically, users get banned for hours at a time. – Gili Apr 24 '17 at 15:42
  • @Gili the point I was trying to make is that it would be incongruous to tell people "you can retry after >= 0 seconds" and then ban them when they do it after e.g. 50ms. – Josip Rodin May 03 '17 at 19:01
  • 4
    According to the docs and use cases, `Retry-After` is only to be used with `503`, `429` and `301`. It is not suggested for `202`. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After The RFC https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html mentions: "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." – Thomas BDX Oct 03 '19 at 15:26