Question

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...).

Was it helpful?

Solution

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.

OTHER TIPS

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?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top