Subject: PATCH, Expect, Prefer, etc

From: James M Snell <[email-masked]>
Date: Thu, 02 Aug 2007 23:18:20 -0700

Ok, the recent conversation around the use of the 200/204 status codes
in the current PATCH draft has indicated that a couple of new status
codes and a new request header would likely be helpful. So how about
something like this:

---
208 Content Returned

The request has succeeded.  The information returned with the response
is equivalent to what would be returned in a subsequent GET on the resource.

418 Preference Failed

The preference given in a Prefer request-header field was understood by
could not be met by this server.

Prefer header

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

  Prefer = "Prefer" ":" 1#preference

  preference  = "208-content-returned" |
                "204-no-content" |
                preference-extension

  preference-extension = token [ "=" ( token | quoted-string )
                         *preference-params ]

  preference-params = ";" token [ "=" ( token | quoted-string ) ]

A server that does not understand or is unable to comply with any of the
preference values in the Prefer field of a request MUST ignore those
values.  The server MAY response with a 418 (Preference Failed) status
if any of the preferences cannot be met.

This header field is defined with extensible syntax to allow for future
extensions.  If a server receives a request containing a Prefer field
that includes a preference-extension that it does not support, it MUST
ignore that extension.

Comparison of preference values is case-insensitive for unquoted tokens
including 208-content-returned and 204-no-content, and is case-sensitive
for quoted-string expectation-extensions.

The Prefer mechanism is hop-by-hop; that is, an HTTP/1.1 proxy MAY
fulfill a Preference if it receives a request with a preference it can
meet.  However, the Prefer request-header itself is end-to-end; it MUST
be forwarded if the request is forwarded.

A Prefer field that includes the 208-content-returned value indicates
that the client prefers that the server respond with a 208 status.

A Prefer field that includes the 204-no-content value indicates that the
client prefers that the server respond with a 204 status.
---

Example 1: Successful response, preference fulfilled

PATCH /foo HTTP/1.1
Prefer: 208-content-returned
Content-Type: ...

{patch document}

HTTP/1.1 208 Content Returned
Content-Type: ...
Etag: ...

{resource content}

---

Example 2: Successful response, preference fulfilled

PATCH /foo HTTP/1.1
Prefer: 204-no-content
Content-Type: ...

{patch document}

HTTP/1.1 204 No Content

---

Example: Successful response, preference ignored

PATCH /foo HTTP/1.1
Prefer: 208-content-returned
Content-Type: ...

{patch document}

HTTP/1.1 200 OK
Content-Type: ...
Warning: 601 server "Preference Ignored"

{some data}

---

Example: Successful response, preference fulfilled by a proxy rather
than the origin server

PATCH /foo HTTP/1.1
Prefer: 204-no-content
Content-Type: ...

{patch document}

HTTP/1.1 204 No-Content
Warning: 602 proxy "Preference Fulfilled

---

Example: Server chose not to fulfill or ignore the preference

PATCH /foo HTTP/1.1
Prefer: 208-content-returned
Content-Type: ...

{patch document}

HTTP/1.1 418 Preference Failed

{error response}

---

The Prefer header is defined to be generally identical to Expect with
the difference being that Prefer MUST be ignored if it is not
understood.  A server can choose not to fulfill a preference and
communicate that choice to the client using 418, but proxies are
required to forward them on.

A proxy can choose to fulfill a preference if it is capable.  For
instance, a proxy that receives a 200 or 209 response to a request that
contains Prefer: 204-no-content can choose to return 204 No Content to
the client rather than the complete original response.  If the request
contains 209-content-returned and the server responds with 200 or 204
(or whatever), then it obviously will not be capable of fulfilling the
preference and must ignore it.

Thoughts?

- James

---

From: Julian Reschke <[email-masked]>
Date: Fri, 03 Aug 2007 09:35:13 +0200

> codes and a new request header would likely be helpful. So how about

209. (see 
<http://tools.ietf.org/html/draft-ietf-webdav-bind-19#section-12>).

> is equivalent to what would be returned in a subsequent GET on the resource.

This may need to state something about variant selection.

> could not be met by this server.

I'm not sure this should even be an error condition. Wouldn't it be 
wiser to just let the server execute the operation? It's "preference", 
not "expectation", after all.

> values.  The server MAY response with a 418 (Preference Failed) status

s/response/respond/

> ...

Also, I'd clarify that the default response for a successful PATCH would 
be 204, not 208.

And then, this probably should go into a separate spec :-).

Best regards,

Julian

---

From: Stefan Eissing <[email-masked]>
Date: Fri, 3 Aug 2007 09:42:03 +0200

> preference and must ignore it.

+1.

One suggestion: when documenting 204 as default, i think one can  
eliminate "204-no-content". Functionality is the same, deterministic  
what servers default to, less code in server.

--
Stefan Eissing

<green/>bytes GmbH
Hafenweg 16
D-48155 Münster
Germany
Amtsgericht Münster: HRB5782

---

From: "Mark Baker" <[email-masked]>
Date: Fri, 3 Aug 2007 08:44:02 -0400

> not "expectation", after all.

+1

> Also, I'd clarify that the default response for a successful PATCH would

Why would a default be needed?

> And then, this probably should go into a separate spec :-).

Mark.
-- 
Mark Baker.  Ottawa, Ontario, CANADA.         http://www.markbaker.ca
Coactus; Web-inspired integration strategies  http://www.coactus.com

---

From: Julian Reschke <[email-masked]>
Date: Fri, 03 Aug 2007 14:52:31 +0200

> Why would a default be needed?

OK, let me rephrase that: I don't want a default status, but a default 
preference; and that should be not to return the whole entity.

Best regards, Julian

---

From: Cyrus Daboo <[email-masked]>
Date: Fri, 03 Aug 2007 09:27:09 -0400

Hi Julian,

> preference; and that should be not to return the whole entity.

+1 The client should be the one to decide whether the new entity is 
returned or not, and we need an appropriate header for the client to 
indicate that decision to the server. We should also extend PUT/POST to 
support that new header too so that the new entity after a PUT/POST could 
be returned.

-- 
Cyrus Daboo

---

From: Julian Reschke <[email-masked]>
Date: Fri, 03 Aug 2007 15:34:15 +0200

Cyrus Daboo wrote:
> support that new header too so that the new entity after a PUT/POST 
> could be returned.

+1

Correct. This could be the missing piece for 
<http://greenbytes.de/tech/webdav/draft-reschke-http-etag-on-write-latest.html>, 
allowing the client to tell the server that it wants the new entity to 
be sent back if it's not identical to what was PUT.

Best regards, Julian

---

From: "Mark Baker" <[email-masked]>
Date: Fri, 3 Aug 2007 09:49:54 -0400

> preference; and that should be not to return the whole entity.

I can see the value in that, but I'd prefer it if a message without a
Prefer header had the same meaning as it does now; no preference.  So
perhaps a new value indicating preference for 204 would be the thing
to do.

Mark.

---

From: James M Snell <[email-masked]>
Date: Fri, 03 Aug 2007 14:52:51 -0700

Julian Reschke wrote:
>[snip]

Ah, right. I had thought I'd seen 208 used somewhere before. Thanks for
the reference.

> This may need to state something about variant selection.

Likely. Do you have a specific suggestion?

> not "expectation", after all.

Well, the issue here is that it is not clear whether or not the server
did not understand a preference or just decided not to honor it.  If
there's no real value in that distinction, then yes, this code is not
necessary.

> [snip]

I'm assuming you meant the default preference for a successful PATCH.
There would be no default response.

> And then, this probably should go into a separate spec :-).

Likely.

- James

---

From: Julian Reschke <[email-masked]>
Date: Sat, 04 Aug 2007 20:54:43 +0200

> Likely. Do you have a specific suggestion?

Hm.

Everything is simple as long as the resource addressed by the 
Request-URI doesn't do content negotiation. Maybe it would make sense 
just to require that.

Otherwise we'll have to do some cleanup in the method definition. The 
patch is applied to an entity, not the resource, right. So we probably 
should use the much-loved term "requested variant" from RFC2616, and 
then later on state that the entity returned with a 209 status is the 
new version of the requested variant.

> there's no real value in that distinction, then yes, this code is not

I'm not sure it's needed. But if it is needed, a status code won't 
scale. If a request has multiple preferences, and the server only meets 
some of them, something more complex would be needed, such as as 
"Preferences-Met" response header.

> There would be no default response.

Yep.

Best regards, Julian

---

From: Henrik Nordstrom <[email-masked]>
Date: Mon, 06 Aug 2007 17:45:13 +0200

> preference and must ignore it.

Can't it? What stops the proxy from issuing a GET in that case and
returning the 200 response as a 209?

Note: Not saying it's generally a good thing or even desired for a proxy
to do, and only makes sense in very special controlled deployments.

Regards
Henrik

---

From: James M Snell <[email-masked]>
Date: Mon, 06 Aug 2007 10:46:33 -0700

I suppose the proxy *could* issue a subsequent GET, it would just be
impossible to ensure that the result is accurate.  E.g. the resource
might be modified between the initial response and the subsequent GET,
which somewhat defeats the purpose of the 209 response (at least when
used with PATCH).  I'm not sure we'd want to encourage this behavior at
all, even in highly controlled environments.

- James

---

From: Julian Reschke <[email-masked]>
Date: Mon, 06 Aug 2007 19:55:59 +0200

> all, even in highly controlled environments.

That could be handled using "If-Match", right?

Best regards, Julian