CURLcode result = CURLE_OK;
data->state.expect100header = FALSE; /* default to false unless it is set
to TRUE below */
- if(use_http_1_1plus(data, conn) &&
+ if(!data->state.disableexpect && use_http_1_1plus(data, conn) &&
(conn->httpversion < 20)) {
/* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
Expect: 100-continue to the headers which actually speeds up post
*/
Curl_expire_done(data, EXPIRE_100_TIMEOUT);
if(!k->upload_done) {
- if(data->set.http_keep_sending_on_error) {
+ if((k->httpcode == 417) && data->state.expect100header) {
+ /* 417 Expectation Failed - try again without the Expect
+ header */
+ infof(data, "Got 417 while waiting for a 100\n");
+ data->state.disableexpect = TRUE;
+ DEBUGASSERT(!data->req.newurl);
+ data->req.newurl = strdup(conn->data->change.url);
+ Curl_done_sending(conn, k);
+ }
+ else if(data->set.http_keep_sending_on_error) {
infof(data, "HTTP error before end of send, keep sending\n");
if(k->exp100 > EXP100_SEND_DATA) {
k->exp100 = EXP100_SEND_DATA;
BIT(ftp_trying_alternative);
BIT(wildcardmatch); /* enable wildcard matching */
BIT(expect100header); /* TRUE if we added Expect: 100-continue */
+ BIT(disableexpect); /* TRUE if Expect: is disabled due to a previous
+ 417 response */
BIT(use_range);
BIT(rangestringalloc); /* the range string is malloc()'ed */
BIT(done); /* set to FALSE when Curl_init_do() is called and set to TRUE
idle do nothing after receiving the request, just "sit idle"
stream continuously send data to the client, never-ending
writedelay: [secs] delay this amount between reply packets
-skip: [num] instructs the server to ignore reading this many bytes from a PUT
- or POST request
-
+skip: [num] instructs the server to ignore reading this many bytes from a
+ PUT or POST request
rtp: part [num] channel [num] size [num]
stream a fake RTP packet for the given part on a chosen channel
with the given payload size
-
connection-monitor When used, this will log [DISCONNECT] to the server.input
log when the connection is disconnected.
upgrade when an HTTP upgrade header is found, the server will upgrade
to http2
swsclose instruct server to close connection after response
+no-expect don't read the request body if Expect: is present
For TFTP:
writedelay: [secs] delay this amount between reply packets (each packet being
test325 test326 test327 test328 test329 test330 test331 test332 test333 \
test334 test335 test336 test337 test338 test339 test340 test341 test342 \
test343 \
-test350 test351 test352 test353 test354 test355 test356 \
+test350 test351 test352 test353 test354 test355 test356 test357 \
test393 test394 test395 \
\
test400 test401 test402 test403 test404 test405 test406 test407 test408 \
--- /dev/null
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP PUT
+Expect
+</keywords>
+</info>
+# Server-side
+<reply>
+# 417 means the server didn't like the Expect header
+<data>
+HTTP/1.1 417 OK swsbounce
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+
+</data>
+<data1>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 10
+
+blablabla
+</data1>
+<datacheck>
+HTTP/1.1 417 OK swsbounce
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 10
+
+blablabla
+</datacheck>
+<servercmd>
+no-expect
+</servercmd>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP PUT with Expect: 100-continue and 417 response
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/we/want/357 -T log/test357.txt
+</command>
+<file name="log/test357.txt">
+Weird
+ file
+ to
+ upload
+for
+ testing
+the
+ PUT
+ feature
+</file>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+PUT /we/want/357 HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+Accept: */*\r
+Content-Length: 78\r
+Expect: 100-continue\r
+\r
+PUT /we/want/357 HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+Accept: */*\r
+Content-Length: 78\r
+\r
+Weird
+ file
+ to
+ upload
+for
+ testing
+the
+ PUT
+ feature
+</protocol>
+</verify>
+</testcase>
int rcmd; /* doing a special command, see defines above */
int prot_version; /* HTTP version * 10 */
int callcount; /* times ProcessRequest() gets called */
+ bool skipall; /* skip all incoming data */
+ bool noexpect; /* refuse Expect: (don't read the body) */
bool connmon; /* monitor the state of the connection, log disconnects */
bool upgrade; /* test case allows upgrade to http2 */
bool upgrade_request; /* upgrade request found and allowed */
/* close connection */
#define CMD_SWSCLOSE "swsclose"
+/* deny Expect: requests */
+#define CMD_NOEXPECT "no-expect"
+
#define END_OF_HEADERS "\r\n\r\n"
enum {
logmsg("instructed to skip this number of bytes %d", num);
req->skip = num;
}
+ else if(!strncmp(CMD_NOEXPECT, cmd, strlen(CMD_NOEXPECT))) {
+ logmsg("instructed to reject Expect: 100-continue");
+ req->noexpect = TRUE;
+ }
else if(1 == sscanf(cmd, "writedelay: %d", &num)) {
logmsg("instructed to delay %d secs between packets", num);
req->writedelay = num;
req->open = FALSE; /* closes connection */
return 1; /* done */
}
- req->cl = clen - req->skip;
+ if(req->skipall)
+ req->cl = 0;
+ else
+ req->cl = clen - req->skip;
logmsg("Found Content-Length: %lu in the request", clen);
if(req->skip)
logmsg("... but will abort after %zu bytes", req->cl);
- break;
}
else if(strncasecompare("Transfer-Encoding: chunked", line,
strlen("Transfer-Encoding: chunked"))) {
/* chunked data coming in */
chunked = TRUE;
}
-
+ else if(req->noexpect &&
+ strncasecompare("Expect: 100-continue", line,
+ strlen("Expect: 100-continue"))) {
+ if(req->cl)
+ req->cl = 0;
+ req->skipall = TRUE;
+ logmsg("Found Expect: 100-continue, ignore body");
+ }
if(chunked) {
if(strstr(req->reqbuf, "\r\n0\r\n\r\n")) {
req->digest = FALSE;
req->ntlm = FALSE;
req->skip = 0;
+ req->skipall = FALSE;
+ req->noexpect = FALSE;
req->writedelay = 0;
req->rcmd = RCMD_NORMALREQ;
req->prot_version = 0;