Subject: Pipelining and Expect: 100-continue interaction

From: Marc Schneider <[email-masked]>
Date: Fri, 22 Apr 2005 09:54:22 -0400

What is the proper behavior if a client sends a request to a server using 
the Expect request-header field with the "100-continue" expectation, and 
then pipelines another request before a 100 Contine response is received 
and before the entity body of the first request has been sent?

Is this legal? Are there any known clients that exhibit this behavior?

Thanks,
Marc

Marc Schneider
Senior Software Engineer

OPNET Technologies, Inc. (NASDAQ: OPNT)
tel: +1.240.497.3000
fax: +1.240.497.3001
<http://www.opnet.com/>http://www.opnet.com

====================================================
Register for OPNET's Online Technology Workshops
<http://www.opnet.com/TechWorkshops/>http://www.opnet.com/TechWorkshops/
====================================================
Register for OPNETWORK 2005 (August 22-26, Washington DC)
<http://www.opnet.com/opnetwork2005/>http://www.opnet.com/opnetwork2005/
====================================================

---

From: Jamie Lokier <[email-masked]>
Date: Fri, 22 Apr 2005 16:03:09 +0100

Marc Schneider wrote:
>    What  is  the  proper behavior if a client sends a request to a server
>    using   the   Expect   request-header   field  with  the  100-continue
>    expectation,  and  then pipelines another request before a 100 Contine
>    response  is  received and before the entity body of the first request
>    has been sent?

It's not legal.  If the client doesn't see a 100 Continue response, it
can choose not to send the request body and close the connection.  It
can't omit the body and send another request, not even if it's already
seen a response from the server.

Think about it: after the server sends an error response (without 100
Continue), the server cannot possibly know whether the client has sent
a request body or not.  It might be in flight in the network, because
the client is allowed to time out waiting for 100 Continue then send a
request body.  And because a request body is not syntactically
distinguishable from another request, the server must continue to
listen for a request body or close the connection.  Which means the
client must send it or close the connection.

-- Jamie

---

From: Marc Schneider <[email-masked]>
Date: Fri, 22 Apr 2005 11:36:55 -0400

From section 8.2.3 of RFC 2616:

If it [the origin server] responds with a final status code, it MAY close the
transport connection or it MAY continue to read and discard the rest of the 
request. It MUST NOT perform
the requested method if it returns a final status code.

If the server sends an error response (without 100 Continue), then there 
are two cases:
1) The client started sending the entity body, or
2) The client didn't send the entity body and won't send an entity body.

In case 1, the origin server can continue to read and discard the rest of 
the request, the server doesn't need to close the transport connection and 
once the entity body has been discard the origin server can process other 
requests on the connection.

In case 2, the origin server will keep the connection open and will 
continue to process requests on the connection. The client may then send 
another request.

How would the server know when to discard the data or not to discard the 
data? I could imagine that a server would attempt to parse the data as if 
it was an HTTP request start line and discard the data if it doesn't parse 
correctly. If it does parse correctly, the server would process it as a new 
request. In this case, pipelining of request would be possible.

Is there something specific in the RFC that you could point to that says 
that this is not legal?

Thanks,
Marc

Marc Schneider
Senior Software Engineer

---

From: Marc Schneider <[email-masked]>
Date: Fri, 22 Apr 2005 11:54:09 -0400

I think I found some of what I was looking for in section 8.2.2 of RFC 2616:

Monitoring Connections for Error Status Messages
An HTTP/1.1 (or later) client sending a message-body SHOULD monitor the 
network connection for an error status
while it is transmitting the request. If the client sees an error status, 
it SHOULD immediately cease transmitting the
body. If the body is being sent using a "chunked" encoding (section 3.6), a 
zero length chunk and empty trailer MAY
be used to prematurely mark the end of the message. If the body was 
preceded by a Content-Length header, the
client MUST close the connection.
So, in case 2 below, if the Content-Length was sent, then the client must 
close the connection upon receiving the 417 error from the server. If using 
"chunked" encoding then at most a zero length chunk will be sent, which 
will be discarded.

and from Section 8.1.2.2 of RFC 2616
A client that supports persistent connections MAY "pipeline" its requests 
(i.e., send multiple requests without
waiting for each response).
Since the "request" is complete until the entity body is send (or a zero 
length chunk) then no other requests can be pipelined.

Thanks,
Marc

At 11:36 AM 4/22/2005, Marc Schneider wrote:
>transport connection or it MAY continue to read and discard the rest of 
>the request. It MUST NOT perform
>correctly. If it does parse correctly, the server would process it as a 
>new request. In this case, pipelining of request would be possible.
>

Marc Schneider
Senior Software Engineer

---

From: Jamie Lokier <[email-masked]>
Date: Fri, 22 Apr 2005 18:27:04 +0100

Marc Schneider wrote:

>    I could imagine that a server would attempt to parse the data as
>    if it was an HTTP request start line and discard the data if it
>    doesn't parse correctly.  If it does parse correctly, the server
>    would process it as a new request. In this case, pipelining of
>    request would be possible.

Nice idea, but the request body can start with text that looks exactly
the same as a request header - there's no reliable way to distinguish
them.

Also, if you wrote a client that did this, and even if there is a way
to distinguish them (as there is if the request is chunked), it would
not work with existing servers or proxies.

That's the main problem: to change this feature of the protocol to
allow clients to omit the request body and pipeline, and still be
compatible with existing servers, you need some way for the client
to discover that the server (or proxy) supports the feature.  It would
have to be a HTTP extension.

>    Is there something specific in the RFC that you could point to
>    that says that this is not legal?

It's not made very clear.  But I've asked exactly this question before
on this list, which is why I know the answer.

-- Jamie

---

From: Jamie Lokier <[email-masked]>
Date: Fri, 22 Apr 2005 18:30:07 +0100

Marc Schneider wrote:
>    Since  the  "request"  is complete until the entity body is send (or a
>    zero length chunk) then no other requests can be pipelined.

If you want to make best use of the connection, you can pipeline
requests with bodies when you think it's worth it.  So if your request
body is very small, your client might decided to just send it without
waiting and continue pipelining.

-- Jamie