0

I am trying to find standards-compliant (or good practice-compliant) way of informing the RESTful API server that the API client would prefer specific code, but can handle other codes if necessary.

Namely, for example when creating a resource with POST call to /items URL you can either:

  1. Receive 201 CREATED response containing the representation of newly created resource,
  2. Receive 202 ACCEPTED response if creation needs to wait longer than the server wants to spend on generating and returning the response (eg. because something is done asynchronously),
  3. Receive 204 NO CONTENT response with empty body and some Location header pointing to the location of the resource,

The point is to let the server know, that the API client prefers 201 CREATED with resource representation in the response body, but will accept also any other response. Preference would be signaled for performance reasons (to avoid separate calls for fetching actual resource from the server) and backward compatibility (there are already API clients that may assume server always returns 204 NO CONTENT and they need to fetch resource from the server all the time.

How to express that preference, not causing a failure in receiving the response? Official specification (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.20) does not seem to address that:

14.20 Expect

The Expect request-header field is used to indicate that particular server behaviors are required by the client.

Expect       =  "Expect" ":" 1#expectation
expectation  =  "100-continue" | expectation-extension
expectation-extension =  token [ "=" ( token | quoted-string )
                           *expect-params ]
expect-params =  ";" token [ "=" ( token | quoted-string ) ]

A server that does not understand or is unable to comply with any of the expectation values in the Expect field of a request MUST respond with appropriate error status. The server MUST respond with a 417 (Expectation Failed) status if any of the expectations cannot be met or, if there are other problems with the request, some other 4xx status.

This header field is defined with extensible syntax to allow for future extensions. If a server receives a request containing an Expect field that includes an expectation-extension that it does not support, it MUST respond with a 417 (Expectation Failed) status.

Comparison of expectation values is case-insensitive for unquoted tokens (including the 100-continue token), and is case-sensitive for quoted-string expectation-extensions.

The Expect mechanism is hop-by-hop: that is, an HTTP/1.1 proxy MUST return a 417 (Expectation Failed) status if it receives a request with an expectation that it cannot meet. However, the Expect request-header itself is end-to-end; it MUST be forwarded if the request is forwarded.

Many older HTTP/1.0 and HTTP/1.1 applications do not understand the Expect header.

See section 8.2.3 for the use of the 100 (continue) status.

Of course there is eg. alternative in the form of API versioning, or custom content types (containing version information). But the first one is a hassle (too many versions to support at once, instead of single one that is pretty flexible) and the second seems wrong (custom content types while you always submit eg. XML? nah...).

Tadeck
  • 132,510
  • 28
  • 152
  • 198

2 Answers2

1

I would use query parameters to give hints to the server. Maybe something like ?body=false&wait=5000. wait, in particular, isn't ideal because it futzes with caching - you'll get multiple cache entries for the same response with different wait times. body (or alternately-named equivalent) is more frequently seen.

The other option is to use custom headers, but then you have to watch out for any intermediate servers (proxy, load balancer, intermediate cache) which might strip them.

Have you considered making the wait time a user- or application-level preference?

Eric Stein
  • 13,209
  • 3
  • 37
  • 52
  • I am especially interested with informing server about the preference between `201 CREATED` (with body) and `204 NO CONTENT` (without body), so wait time has nothing to do with that. I wanted API clients to be more intelligent and handle both cases (if they see `201`, they just use returned body, but when they see `204`, they fetch it separately and do the same), but realistic scenario is that they will not be handling it properly, when I change server behavior. Also API client should have a way to say that it does not care about returned representation, so the server do not need to bother... – Tadeck Mar 20 '14 at 19:00
  • Then go with the query parameter. It's not officially standard, but it's in common use. – Eric Stein Mar 20 '14 at 19:08
  • I accepted the other answer, but I pretty much think GET parameters one of the easiest way to implement that. You also mentioned some disadvantages of your solution and confirmed superiority of the other solution, so I am certain you deserve an upvote. – Tadeck Mar 24 '14 at 03:41
1

Expect won't work for this, but the "Prefer" header field might be what you're looking for. See https://datatracker.ietf.org/doc/html/draft-snell-http-prefer-18.

Community
  • 1
  • 1
Julian Reschke
  • 40,156
  • 8
  • 95
  • 98
  • Interesting idea (did not read it fully), but according to this document, it has expired _July 11, 2013_. – Tadeck Mar 20 '14 at 19:00
  • No, it has not, as it has been approved and is in the RFC Publication queue. See . – Julian Reschke Mar 20 '14 at 20:38
  • If this draft is going live, as Julian says (I'm too lazy to check), then I would prefer the Prefer header to the query parameter solution. – Eric Stein Mar 21 '14 at 12:55
  • @JulianReschke: Awesome, it has support for `Prefer: return=representation` vs. `Prefer: return=minimal` headers that basically mean "return `201 CREATED` with body" and "return `204 NO CONTENT` without body", respectively. Definitely would like to implement that :) – Tadeck Mar 21 '14 at 18:50