mnot’s blog

Design depends largely on constraints.” — Charles Eames

Wednesday, 6 February 2008

Another Kind of HTTP Negotiation

Filed under: HTTP Protocol Design Web Web Services

Here’s one that I’ve been wondering about for a while, for the LazyWeb (HTTP Geek Edition);

PUTs and POSTs can result in the creation of new resources, or changes to the state of existing ones. The response to both can contain one of

Usually, a server will just choose which of these is most appropriate, and send it for all such requests. However, I can easily see cases where clients would want to hint to the server what they want back; e.g., a mobile client might prefer nothing, for efficiency, while a publisher might want to get a copy of the article they just submitted back, to make sure that they have any changes to the content locally.

My question is how a client should hint what they want back in such responses, and specifically whether this is purely an application-specific concern (and should therefore be expressed in the request-URI, for example), or is worthy of a standard (thereby better being expressed in a header).

BTW, I don’t think this is a form of content negotiation; that’s about the format of the response, and overloading it for this would produce some problems (e.g., how do you differentiate between an HTML status message and a HTML representation? There are also conflicts with probably resolutions of issue 69).


25 Comments

Mike Amundsen said:

I’ve run into this a few times. Esp. when the “clients” could be either browsers to other machines. Browsers might want a 302 after the POST, but machines might want 204. In many of the cases I ran into, the issue seemed to be tied to the mime-type, but not all.

maybe a “response-variant” header that suggests the preferred response code:

Response-Variant: 204

Wednesday, February 6 2008 at 1:42 AM

James Snell said:

One possibility: http://tools.ietf.org/html/draft-snell-http-prefer-01

Wednesday, February 6 2008 at 1:55 AM

Stefan Eissing said:

James beat me to it: the same discussion we had around the PATCH proposal and James-whip-out-drafts-like-crazy separated his prefer proposal in a separate spec.

Amusingly, “Snell” sounds like “schnell” in German which means quick/fast.

Wednesday, February 6 2008 at 2:03 AM

Mike Amundsen said:

The “prefer” proposal is a great place to start. I also agree that there needs to be some generalized way to register new codes/extensions. Seems this can be handled loosely in the beginning, though.

Wednesday, February 6 2008 at 2:30 AM

James Snell said:

I removed the content-return largely because it was unspecified and needed to be clarified. Suggestions are definitely welcome on what preferences should be defined within the spec.

And, yeah, I agree about the hop-by-hop thing.

Wednesday, February 6 2008 at 2:36 AM

Mike Amundsen said:

On preference extensions: Seems like allowing the client to suggest an HTTP Status is a simple (and fully ‘defined’) extenstion pattern:

Prefer: http-status=204 Prefer: http-status=302 Prefer: http-status=200 (vague but meant to mean return body)

Wednesday, February 6 2008 at 2:58 AM

duryodhan said:

Hey, I don’t get HOW this could be represented in URIs anyways? My understanding forces me to think that something like this needs to be done through headers. Could you please clarify that thought for me a little ?

moving on, with regards to content-negotiation: from the http rfc

” Most HTTP responses include an entity which contains information for interpretation by a human user. Naturally, it is desirable to supply the user with the “best available” entity corresponding to the request. “

Thus, Content-negotiation doesn’t necessarily imply format of the response. Again quoting … “ “content negotiation” – the process of selecting the best representation for a given response when there are multiple representations available. “

Representation for a given response , not necessarily representation of a resource. Thus, for above example , there are two representations of the response :

  1. with the content in the body of the message
  2. with the body of the message empty , (or with links to the actual representation in it).

The fact that it was successful is stated in the response code.

This comes under the purview of the definition of content-negotiation, if I understand it correctly. Infact, imho, putting a Prefer in the headers is just adding another help for server-driven content negotiation(like accept-*). Equivalently, right now, I guess a server can respond to a PUT/POST with a 300, which the client can decide whether to follow or not. This is again, content-negotiation.(agent-driven).

I might be way off, as I am a student right now … so please kindly correct any mistakes I might have made.

Wednesday, February 6 2008 at 3:36 AM

Robert Brewer said:

Sounds to me like a prefect use case for an expectation-extension, such as “204-no-content” instead of “100-continue”.

Wednesday, February 6 2008 at 4:07 AM

James Snell said:

Mike, I like that pattern better than the return-no-content, return-content approach I was originally taking.

Other than expected response status codes, what other kinds of preferences should be defined as part of the spec?

Wednesday, February 6 2008 at 4:28 AM

Dimitri Glazkov said:

Another use case:

XHR currently follows the 302 (http://www.w3.org/TR/2006/WD-XMLHttpRequest-20060405/#dfn-send) which may or may not be a desirable outcome for a front-end application.

Could http-status: 200 provide a way to determine where the 302 would take you?

Wednesday, February 6 2008 at 4:57 AM

Mike Amundsen said:

James:

Well, the http-status version scratches my itch[g].

The other extensions that come to mind involve altering the content that is returned (brief summary abstract full) - seems a tricky item for intermediaries.

Mark, is this heading the direction you envisioned?

Wednesday, February 6 2008 at 5:10 AM

Mike Amundsen said:

Mark:

I am guessing that your original post was about a “no-content content” suggestion and nothing else, right? Were you at all thinking of cases where the server returns 302 and wether “prefer:” would address that?

Wednesday, February 6 2008 at 5:32 AM

Subbu Allamaraju said:

Since the status of what happened can be addressed by existing status/headers, assuming that the server succeeded, the choice is between (a) give me a representation now, or (b) tell me where the updated representation is (in case a new resource is created). Agree that this is not content-negotiation, but is some form of response-negotiation.

Wednesday, February 6 2008 at 6:27 AM

Mike Amundsen said:

Robert:

Ha! Good point. Reading the spec on Expect header leads me to think this might result in lots of 417s from intermediaries, though.

Thursday, February 7 2008 at 1:47 AM

Mike Amundsen said:

I see the merit in iana-registered string values, too.

Am i correct to assume that this is something that would only be valid on PUT/POST, possibly DELETE? That means caching would not be affected.

Thursday, February 7 2008 at 4:25 AM

James Snell said:

Mark, yeah, I see your point. It’s likely better that we set the bar higher and use iana registered string values rather than leave it wide open using the status codes. As an implementor, I like the elegance of the status code approach but it definitely is easier to abuse.

Thursday, February 7 2008 at 7:42 AM

James Snell said:

The Prefer header is defined generically for all HTTP methods, however, the server is given the option of ignoring the Prefer header completely. If the response to a request is affected by a stated preference, Vary: Prefer would need to be included in the response.

Friday, February 8 2008 at 7:45 AM

Mike Amundsen said:

Mark/James:

After my initial excitement about the notion of using http-status as a “Prefer” extension I started thinking about the implications for intermediaries and came to the same spot as Mark: using it for POST/PUT, possibly DELETE is pretty safe. but GET will be messy.

So, I’m down to the following possible responses: no-body (returns 204 or 200) body (returns 200 w/ body) no-redirect (returns 204 or 200) redirect (returns 3xx)

There’s some overlap, but I think that’s OK.

I also think I might help to allow a list of values in order of preference:

no-redirect,no-body,body

Sunday, February 10 2008 at 2:24 AM

Brian Smith said:

You said “a mobile client might prefer nothing, for efficiency.”

In my AtomPub implementation, I just make the response body for a “201 Created” really small, so that it is likely to fit into the same packet as the headers. AtomPub requires me to return an Atom entry, but it doesn’t have to be the exact entry that was created, so I return a minimal atom entry in response to POSTs: it contains just the atom:id, atom:updated, atom:author, atom:link[@rel=’edit’ @rel=’edit-media’], atom:title, and an atom:link[@rel=’alternate’] that duplicates the atom:link[@rel=’edit’] link. (This is basically what is in my collection feed as well.) Then, I compress it if there is an Accept-Encoding: deflate. The result is a response body that is basically indistinguishable, performance-wise, from no response for clients that are going to just ignore the response body. Additionally, if the client has an “Accept:” header that indicates that it prefers text/plain over application/atom+xml, then I can just return the IRI form of the URL in the Location: header in the request body (with “Content-Type: text/plain:charset=UTF-8”).

That doesn’t solve the problem where the client wants to get back a (full) representation of the resource. You said “A publisher might want to get a copy of the article they just submitted back, to make sure that they have any changes to the content locally.” If it is likely that the resulting entry would be the same as the one that was PUT/POSTed, then it is wasteful to transmit the identical copy back to the client just so he can check that it is identical. Most of the use cases for “Prefer: no-content” would be better served with a conditional GET mechanism that says “send me back the new version of the resource if and only if it is different than the version I already have.” “Prefer: no-content” is only useful when the client knows beforehand that the server doesn’t alter submitted content, or when the client truly doesn’t care about the final version of the resource.

A different mechanism would be better, like Reschke’s “ETag on write” proposal: http://tools.ietf.org/html/draft-reschke-http-etag-on-write-08. Unfortunately, that proposal doesn’t work well in the case where the server creates/updates multiple resources at once, and it doesn’t work well at all with AtomPub media collections. I described the problem and a workaround for it at http://www.imc.org/atom-protocol/mail-archive/msg10712.html.

  • Brian

Wednesday, February 13 2008 at 6:47 AM

James Snell said:

Spec updated: http://www.ietf.org/internet-drafts/draft-snell-http-prefer-02.txt

Comments/suggestions are always welcome

Friday, February 15 2008 at 6:06 AM

Creative Commons