During the editorial group teleconference on Friday, we discussed
the STATUS100 issue (i.e., when/whether to send or wait for
"100 (Continue)"). This is a summary of our understanding of
that issue. It was written before the discussion of whether
"Expected" should be hop-by-hop or end-to-end, but I believe
it is still accurate.
-Jeff (for the editorial group)
RFC2068 (section 8.2, "Message Transmission Requirements")
introduces the use of a two-phase mechanism for certain requests,
in which the client sends the request header, then waits for the
server to reply with "100 (Continue)" before sending the request
body. This has led to a confusing discussion, in part because
there are several underlying problems that this was expected to
address.
Our understanding is that the two-phase mechanism solves two
potential problems:
(1) A client sending a request message with a request body
may wish to determine if the server is willing to accept
the request (based on the request headers) before it
transmits the body. In some cases, it may either be
inappropriate, or highly inefficient, for the client to
send the body if the server will reject the message without
looking at the body.
(2) There are race conditions that arise when pipelining
several non-idempotent requests, due to the ambiguity that
arises when the connection is terminated before the client
has received responses to all of the requests it has sent.
The use of the two-phase mechanism can reduce the exposure
to such ambiguities, although it cannot entirely eliminate
them.
Regarding problem #1, we believe that the proposal for an
"Expected" request header resolves the issue. The Expected header
allows the client to be explicit about its intention to wait for a
100 (Continue) response, and so a server should only send it if the
client expects it. (And a client that does not "Expect" a 100
Continue response need not wait for one.) We also believe that the
proposal adequately addresses the issue of compatibility with
deployed implementations that conform to the current wording of
RFC2068, although we would appreciate further experience on that.
Regarding problem #2, we observe that the most conservative
solution is simply "do not pipeline non-idempotent requests."
I.e., if your request stream consists of (conceptually) these two
operations
copy A to B
copy C to A
then you should not send the second operation before verifying that
the first operation has completed successfully. (Otherwise, you
might end up with B being a copy of C, rather than of the original
contents of A.)
What exactly counts as an idempotent request depends on the
particular application. However, a generic client may assume that
GET and HEAD requests, except for those on URLs likely to cause
side effects (see RFC2068 section 13.9, "Side Effects of GET and
HEAD") are idempotent, and that PUT, POST, and DELETE requests are
non-idempotent. A client may also assume that after receiving a
cachable response for a prior request, a repeat of the same method
on the same URL is idempotent (since response cachability implies
idempotency).
This is not a major restriction for "traditional" browser-like
applications, since in most cases these would only pipeline GET
requests (e.g., for imbedded images). There is some concern that
this would reduce the performance advantages of pipelining for
other possible applications of HTTP (e.g., WEBDAV or printing). We
believe that the designers of such applications must be careful to
understand the implications of pipelining for the correctness of
their applications in the face of possible communication failures.
It may be appropriate to layer, above HTTP, a mechanism that
implements the semantics of "begin-transaction" and
"end-transaction" operations, rather than depending on HTTP to
provide so-called "ACID" (atomic, consistent, isolated and durable)
semantics. HTTP is not an ACID protocol.
We also observe that if a client is using the two-phase method
(i.e., is sending "Expect: 100-continue") and has several
non-idempotent operations to perform, it may safely pipeline the
request header of request N+1 after sending the body of request N.
This message is a summary of our understanding of the situation.
If no significant objections are raised, we will rewrite the
relevant portions of the next draft of the HTTP/1.1 specification
to incorporate the necessary changes (which will be far briefer
than this message).
[My best guess about the "relevant portions" is that they would be
limited to these sections of RFC 2068:
8.2 Message Transmission Requirements
10.1.1 100 Continue
14.XXX Expected
Also, section 9.1.2 (Idempotent Methods) may need some revisions.]