cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: POST, 100 continue, and 404

From: Steven Parkes <smparkes_at_smparkes.net>
Date: Thu, 30 Jun 2011 14:46:48 -0700

> Are you possibly using some
> kind of HTTP auth?

No auth; this is a very simple case that doesn't have any auth. I noticed it in a case where I was POSTing to an endpoint I hadn't implemented yet, thus producing the 404.

> Why should it? The whole purpose of Expect: 100-continue is to avoid having to
> send the request body in a case like this when the server can tell the client
> at once that the request (and body) isn't wanted.

This seemed to be covered in some depth in

   http://permalink.gmane.org/gmane.comp.web.curl.library/5947

as related to auth. Moreover, I don't see anything in rfc2616 that would indicate the behavior for 404 should be any different than that for 401. It specs the behavior for "a final status code".

The line I keyed off of in that email with respect to rational was

 "Before receiving the 401, client MAY have sent some of the request body"

my interpretation being the reason you have to transmit the body anyway is because the server has no way to ascertain that the client hasn't already started sending the body. In other words, if it's not required, the server has no idea how much data might be coming and so can't skip to the next request; it would be forced to ditch the connection.

I agree that this seems at first blush to mitigate the value of using 100-continue, but both the client and the server can still improve on this "send it anyway" behavior:

- the server can close the connection (and could even be smart, looking at the content length to decide if getting the data is more expensive than recreating a connection).
- the client can use chunked encoding (this need-the-body only happens when content length has been passed by the client in the header)

http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html says, in 8.2.3 under "Requirements for HTTP/1.1 origin servers":

      - Upon receiving a request which includes an Expect request-header
        field with the "100-continue" expectation, an origin server MUST
        either respond with 100 (Continue) status and continue to read
        from the input stream, or respond with a final status code. The
        origin server MUST NOT wait for the request body before sending
        the 100 (Continue) response. If it 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.

Earlier today I think I read somewhere where someone was suggesting a wording change since the 'it MAY ... or it MAY' might be construed to not be the complete set of choices. My spec-ease isn't so expert that I know if that's the case. Unfortunately, now I can't find the reference.

> Can you wireshark the connection or use CURLOPT_DEBUGFUNCTION to figure out
> exactly what is sent and isn't sent in both the requests to figure out what's
> wrong in the second one?

Yeah. I've seen the bytes on the wire. It definitely looks like libcurl is not sending the body, which I think we agree is the case? There's some question of why this is screwing up nginx. It doesn't give an exact error so I'm extrapolating a bit. On the next request, nginx says it saw a 400 bad request, with a request line of " */*". I haven't exactly calculated the offsets, but it looks like it's skipping Content-Length bytes from the previous request (which libcurl never sent) and then trying to start a new request. It's ending up in the middle of the headers of the next request, in the middle of a header like "Accept: */*".
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2011-06-30