cURL / Mailing Lists / curl-users / Single Mail

curl-users

Re: one second delay in HTTP PUT

From: Dan Fandrich <dan_at_coneharvesters.com>
Date: Sat, 20 Sep 2008 23:34:36 -0700

On Sun, Sep 21, 2008 at 12:19:13AM -0400, Gary Lawrence Murphy wrote:
> I have two programs, one is a C-language program using libcurl (Linux)
> to send a document to a perl-based receiver (also Linux), but the
> conversation I see between the two machines is very strange:
>
> 1. 18:05:34.974033: receives "PUT / HTTP/1.1" header from libcurl PUT
> server; the packet (in tcpdump) shows that it has Accept: */* and
> Content-Length: 1095, then ends with "Expect: 100-continue"
>
> 2. 18:05:34.974049: client sends ACK
>
> 3. 18:05:34.976442: client sends an HTTP response which contains
> "(HTTP/1.1 100 Continue"
>
> 4. 18:05:35.065209: client receives ACK from libcurl server
>
> 5. 18:05:36.065523: client receives the HTTP body from libcurl
>
> Forgive my noviceness, but there's two things I don't understand here,
> and one of them is bogging down my transmissions:
>
> - Why doesn't the HTTP PUT message already contain the body? In the C

This question has been hashed out many times before on this list (it
should probably be added to the FAQ). The idea is to avoid sending a huge
file only to have the server return a 401 Authorization Required or
other error code and then have to send it all again. It's very rare
for a server to allow an unauthenticated PUT, after all.

> code I set up the curl call as one atomic item containing headers and
> the body expecting this to be one transmission; why does the client
> need to send an HTTP 100-continue response to the original request?
> Is this discussed in RFC 2616? (I must have missed it) or is this
> perhaps an ill-configured PUT request?
>
> - I can live with 100-Continue handshakes, but here is the really
> bothersome part: Notice how the delay between the 100 Continue request
> and the start of the response with the body is very nearly exactly one
> second! I see this on every transfer. Why one second? that seems a
> long time for a pause when the typical HTTP transmission is only a few
> K in size. Again, is there perhaps some misconfig of the libcurl that
> is causing this?

The 1 second timeout is hard-coded in libcurl. Since HTTP 1.0 servers don't
support 100-continue, this is a fallback mechanism that allows a transfer
to continue anyway.

> Here's the sequence of curl library calls:
>
> curl = curl_easy_init();
> if (!curl) return NULL;
>
> curl_easy_setopt(curl, CURLOPT_DNS_CACHE_TIMEOUT, 150);
> curl_easy_setopt(curl, CURLOPT_TIMEOUT, RESTIMEOUT);
> curl_easy_setopt(curl, CURLOPT_MAXCONNECTS, 1);
> curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, TRUE);
>
> curl_easy_setopt(curl, CURLOPT_READDATA, mem_buffer);
> curl_easy_setopt(curl, CURLOPT_URL, target);
> curl_easy_setopt(curl, CURLOPT_UPLOAD, TRUE) ;
>
> curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, TRUE);
> sprintf( string, "Content-Type: text/xml; charset=\"%s\"", charset);
> slist = curl_slist_append(slist, string );
> curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
> curl_easy_setopt(curl, CURLOPT_INFILESIZE, file_size);
> res = curl_easy_perform(curl);

Interesting--no authentication options. I take it this isn't a publically-
accessible server.

> Why is curl_easy_perform(curl) introducing that one-second pause? Can
> it be avoided?

Sure it can--just set an empty Expect: header with CURLOPT_HTTPHEADER or
set HTTP 1.0 mode with CURLOPT_HTTP_VERSION. The CVS version of curl will
also automatically disable Expect: if it knows that the server only
supports HTTP 1.0 (which isn't always possible to tell).

>>> Dan

-- 
http://www.MoveAnnouncer.com              The web change of address service
          Let webmasters know that your web site has moved
-------------------------------------------------------------------
List admin: http://cool.haxx.se/cgi-bin/mailman/listinfo/curl-users
FAQ:        http://curl.haxx.se/docs/faq.html
Etiquette:  http://curl.haxx.se/mail/etiquette.html
Received on 2008-09-21