diff --git a/lib/http.c b/lib/http.c index dcb5674bc86337fcbc2f4bf8f844566700b3684e..5be8a9e6f080527069a6fa29632a4231fcf48e13 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1067,7 +1067,6 @@ CURLcode Curl_http(struct connectdata *conn) char *ptr; char *request; bool authdone=TRUE; /* if the authentication phase is done */ - Curl_HttpReq httpreq; /* type of HTTP request */ if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ @@ -1467,13 +1466,11 @@ CURLcode Curl_http(struct connectdata *conn) http->postdata = NULL; /* nothing to post at this point */ Curl_pgrsSetUploadSize(data, 0); /* upload size is 0 atm */ - if(!authdone) - /* until the auth is done, pretend we only do GET */ - httpreq = HTTPREQ_GET; - else - httpreq = data->set.httpreq; + /* If 'authdone' is still FALSE, we must not set the write socket index to + the Curl_transfer() call below, as we're not ready to actually upload + any data yet. */ - switch(httpreq) { + switch(data->set.httpreq) { case HTTPREQ_POST_FORM: if(Curl_FormInit(&http->form, http->sendit)) { @@ -1538,8 +1535,8 @@ CURLcode Curl_http(struct connectdata *conn) /* setup variables for the upcoming transfer */ result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - FIRSTSOCKET, - &http->writebytecount); + authdone?FIRSTSOCKET:-1, + authdone?&http->writebytecount:NULL); if(result) { Curl_formclean(http->sendit); /* free that whole lot */ return result; @@ -1554,7 +1551,16 @@ CURLcode Curl_http(struct connectdata *conn) "Content-Length: %" FORMAT_OFF_T "\r\n", /* size */ data->set.infilesize ); - add_bufferf(req_buffer, "\r\n"); + if(!checkheaders(data, "Expect:")) { + /* if not disabled explicitly we add a Expect: 100-continue + to the headers which actually speeds up post operations (as + there is one packet coming back from the web server) */ + add_bufferf(req_buffer, + "Expect: 100-continue\r\n"); + data->set.expect100header = TRUE; + } + + add_buffer(req_buffer, "\r\n", 2); /* end of headers */ /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, (double)data->set.infilesize); @@ -1568,8 +1574,8 @@ CURLcode Curl_http(struct connectdata *conn) /* prepare for transfer */ result = Curl_Transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - FIRSTSOCKET, - &http->writebytecount); + authdone?FIRSTSOCKET:-1, + authdone?&http->writebytecount:NULL); if(result) return result; break; @@ -1597,15 +1603,19 @@ CURLcode Curl_http(struct connectdata *conn) add_bufferf(req_buffer, "Content-Type: application/x-www-form-urlencoded\r\n"); - add_buffer(req_buffer, "\r\n", 2); - if(data->set.postfields) { - if(postsize < (100*1024)) { + if(authdone && (postsize < (100*1024))) { + /* If we're not done with the authentication phase, we don't expect + to actually send off any data yet. Hence, we delay the sending of + the body until we receive that friendly 100-continue response */ + /* The post data is less than 100K, then append it to the header. This limit is no magic limit but only set to prevent really huge POSTs to get the data duplicated with malloc() and family. */ + add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + if(!conn->bits.upload_chunky) /* We're not sending it 'chunked', append it to the request already now to reduce the number if send() calls */ @@ -1630,9 +1640,22 @@ CURLcode Curl_http(struct connectdata *conn) /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, http->postsize); + + if(!authdone && !checkheaders(data, "Expect:")) { + /* if not disabled explicitly we add a Expect: 100-continue to the + headers which actually speeds up post operations (as there is + one packet coming back from the web server) */ + add_bufferf(req_buffer, + "Expect: 100-continue\r\n"); + data->set.expect100header = TRUE; + } + + add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ } } else { + add_buffer(req_buffer, "\r\n", 2); /* end of headers! */ + /* set the upload size to the progress meter */ Curl_pgrsSetUploadSize(data, (double)data->set.infilesize); diff --git a/tests/data/test10 b/tests/data/test10 index ad2c11473108ed417a5c2bd6929a7f0b63c261a3..9136ec189ca915d4d493ecc3ad66dc91b1e6cb3d 100644 --- a/tests/data/test10 +++ b/tests/data/test10 @@ -45,6 +45,7 @@ Host: 127.0.0.1:8999 Pragma: no-cache Accept: */* Content-Length: 78 +Expect: 100-continue Weird file diff --git a/tests/data/test33 b/tests/data/test33 index 9702453e5ec6c6f73040f3fcb22a54b458894947..ed758e9a89182b6170ccbf0eb307d1515679ecd8 100644 --- a/tests/data/test33 +++ b/tests/data/test33 @@ -44,6 +44,7 @@ Host: 127.0.0.1:8999 Pragma: no-cache Accept: */* Content-Length: 50 +Expect: 100-continue 012345678 012345678 diff --git a/tests/data/test58 b/tests/data/test58 index ce83852d4d4f5e12189d1adbd9a6c9fbe365b458..0ff07c34e93c568e4339a3368f1bb649635e6fd9 100644 --- a/tests/data/test58 +++ b/tests/data/test58 @@ -37,6 +37,7 @@ Host: 127.0.0.1:8999 Pragma: no-cache Accept: */* Content-Length: 12 +Expect: 100-continue a few bytes </protocol> diff --git a/tests/data/test60 b/tests/data/test60 index b58fc15767059c25aa9bf88e4906df2e7a3a380a..fc358c15ae0682bb754f4dac8f44a36f25f963f6 100644 --- a/tests/data/test60 +++ b/tests/data/test60 @@ -38,6 +38,7 @@ Pragma: no-cache Accept: */* Transfer-Encoding: chunked Content-Length: 1 +Expect: 100-continue 13 more than one byte diff --git a/tests/data/test88 b/tests/data/test88 index 532418020972dabac6586aaa7f1432caadd151b5..401de7ba0f7a5efa116e53b28f48e7fa6765336a 100644 --- a/tests/data/test88 +++ b/tests/data/test88 @@ -1,5 +1,8 @@ # Server-side <reply> +<servercmd> +auth_required +</servercmd> <data> HTTP/1.1 401 Authorization Required swsclose Server: Apache/1.3.27 (Darwin) PHP/4.1.2 @@ -63,6 +66,8 @@ PUT /88 HTTP/1.1 Host: 127.0.0.1:8999 Pragma: no-cache Accept: */* +Content-Length: 85 +Expect: 100-continue PUT /88 HTTP/1.1 Authorization: Digest username="testuser", realm="testrealm", nonce="1053604145", uri="/88", response="78a49fa53d0c228778297687d4168e71" @@ -71,6 +76,7 @@ Host: 127.0.0.1:8999 Pragma: no-cache Accept: */* Content-Length: 85 +Expect: 100-continue This is data we upload with PUT a second line diff --git a/tests/data/test98 b/tests/data/test98 index 86033c8218da98e2f4079c4244319f8dbe07f8f8..565b30d1db1d00901aad9da15507eeef47cd0f2d 100644 --- a/tests/data/test98 +++ b/tests/data/test98 @@ -40,6 +40,7 @@ Host: 127.0.0.1:8999 Pragma: no-cache Accept: */* Content-Length: 14 +Expect: 100-continue data on stdin </protocol>