I'm writing a simplistic HTTP server that will accept PUT requests mostly from cURL as client and I'm having a bit of an issue with handling the Expect: 100-continue
header.
As I understand it, the server is supposed to read the header, send back a HTTP/1.1 100 Continue
response on the connection, read the stream up to the value on Content-Length
and then send back the real response code (Usually HTTP/1.1 200 OK
but any other valid HTTP answer should do).
Well, that's exactly what my server does. The problem is that, apparently, if I send a 100 Continue
answer, cURL fails to report any subsequent HTTP error code and assumes the upload was a success. For instance, if the upload is rejected due to the nature of the content (there is a basic data check happening), I want the calling client to detect the problem and act accordingly.
Am I missing something obvious ?
edit: here is a sample output from cURL with a secondary header containing an error:
> PUT /test1%2Epdf HTTP/1.1 > Authorization: Basic xxxx > User-Agent: curl/7.20.0 (i386-pc-win32) libcurl/7.20.0 OpenSSL/0.9.8l zlib/1.2.3 > Host: localhost > Accept: */* > Content-Length: 24 > Expect: 100-continue > < HTTP/1.1 100 Continue < HTTP/1.1 415 Unsupported Media Type < Connection: close < Content-Type: text/xml < Content-Length: 289 <
The client will expect to receive a 100-Continue response from the server to indicate that the client should send the data to be posted. This mechanism allows clients to avoid sending large amounts of data over the network when the server, based on the request headers, intends to reject the request.
When the connection to the server is established, the request--including the headers, the Expect: 100-Continue header, without the request body--is then transmitted to the server. The client then waits for a response from the server.
The HTTP 200 OK success status response code indicates that the request has succeeded. A 200 response is cacheable by default. The meaning of a success depends on the HTTP request method: GET : The resource has been fetched and is transmitted in the message body.
I know this is old, but here is my understanding of "100 Continue"
Your server is supposed to validate the request based on header alone from the client i.e. if the request is invalid, don't send "100 Continue" but actual http error instead e.g. 403. This should prevent the client from posting the data which I understand is the whole point of roundtrip to the server (i.e. client waiting for "100 Continue") in the first place.
If you are validating actual posted data, then you need to apply higher-level protocol here i.e. send your error wrapped in valid HTTP response content. Yes, it seems like limitation and I'm not assuming it's protocol limitation; more likely client confusion having to handle server response more than once.
If you are using libcURL to write your client-side program, make sure you set the CURLOPT_FAILONERROR
option to 1
. For example, in C, you would do something like:
curl_easy_setopt (curl_handle, CURLOPT_FAILONERROR, 1L);
According to the libcURL documentation, this option "tells the library to fail silently if the HTTP code returned is equal to or larger than 400."
Furthermore, the documentation makes it clear that "the default action would be to return the page normally, ignoring that code."
If you are using the curl command line tool, simply adding -f
or --fail
into your curl command will cause similar behaviour as described above. This is also described in the curl man page.
Note that both these methods are not fail-safe, as is clearly stated in the docs:
"This method is not fail-safe and there are occasions where non-successful response codes will slip through, especially when authentication is involved (response codes 401 and 407)."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With