diff options
-rw-r--r-- | lib/http.c | 24 | ||||
-rw-r--r-- | lib/http2.c | 2 | ||||
-rw-r--r-- | lib/mqtt.c | 2 | ||||
-rw-r--r-- | lib/rtsp.c | 6 | ||||
-rw-r--r-- | lib/setopt.c | 23 | ||||
-rw-r--r-- | lib/transfer.c | 39 | ||||
-rw-r--r-- | lib/url.c | 12 | ||||
-rw-r--r-- | lib/urldata.h | 3 | ||||
-rw-r--r-- | lib/vquic/ngtcp2.c | 2 | ||||
-rw-r--r-- | lib/vquic/quiche.c | 2 | ||||
-rw-r--r-- | tests/data/Makefile.inc | 2 | ||||
-rw-r--r-- | tests/data/test1633 | 97 |
12 files changed, 154 insertions, 60 deletions
diff --git a/lib/http.c b/lib/http.c index 0c3df4c50..a0d3eca24 100644 --- a/lib/http.c +++ b/lib/http.c @@ -431,7 +431,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) skip this rewinding stuff */ return CURLE_OK; - switch(data->set.httpreq) { + switch(data->state.httpreq) { case HTTPREQ_GET: case HTTPREQ_HEAD: return CURLE_OK; @@ -452,7 +452,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) } else { /* figure out how much data we are expected to send */ - switch(data->set.httpreq) { + switch(data->state.httpreq) { case HTTPREQ_POST: case HTTPREQ_PUT: if(data->state.infilesize != -1) @@ -594,8 +594,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) #endif if(pickhost || pickproxy) { - if((data->set.httpreq != HTTPREQ_GET) && - (data->set.httpreq != HTTPREQ_HEAD) && + if((data->state.httpreq != HTTPREQ_GET) && + (data->state.httpreq != HTTPREQ_HEAD) && !conn->bits.rewindaftersend) { result = http_perhapsrewind(conn); if(result) @@ -616,8 +616,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) authentication is not "done" yet and no authentication seems to be required and we didn't try HEAD or GET */ - if((data->set.httpreq != HTTPREQ_GET) && - (data->set.httpreq != HTTPREQ_HEAD)) { + if((data->state.httpreq != HTTPREQ_GET) && + (data->state.httpreq != HTTPREQ_HEAD)) { data->req.newurl = strdup(data->change.url); /* clone URL */ if(!data->req.newurl) return CURLE_OUT_OF_MEMORY; @@ -1774,11 +1774,11 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, header as that will produce *two* in the same request! */ checkprefix("Host:", compare)) ; - else if(data->set.httpreq == HTTPREQ_POST_FORM && + else if(data->state.httpreq == HTTPREQ_POST_FORM && /* this header (extended by formdata.c) is sent later */ checkprefix("Content-Type:", compare)) ; - else if(data->set.httpreq == HTTPREQ_POST_MIME && + else if(data->state.httpreq == HTTPREQ_POST_MIME && /* this header is sent later */ checkprefix("Content-Type:", compare)) ; @@ -1915,7 +1915,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) const char *te = ""; /* transfer-encoding */ const char *ptr; const char *request; - Curl_HttpReq httpreq = data->set.httpreq; + Curl_HttpReq httpreq = data->state.httpreq; #if !defined(CURL_DISABLE_COOKIES) char *addcookies = NULL; #endif @@ -3320,7 +3320,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, if((k->size == -1) && !k->chunk && !conn->bits.close && (conn->httpversion == 11) && !(conn->handler->protocol & CURLPROTO_RTSP) && - data->set.httpreq != HTTPREQ_HEAD) { + data->state.httpreq != HTTPREQ_HEAD) { /* On HTTP 1.1, when connection is not to get closed, but no Content-Length nor Transfer-Encoding chunked have been received, according to RFC2616 section 4.4 point 5, we @@ -3415,7 +3415,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, * continue sending even if it gets discarded */ - switch(data->set.httpreq) { + switch(data->state.httpreq) { case HTTPREQ_PUT: case HTTPREQ_POST: case HTTPREQ_POST_FORM: @@ -3671,7 +3671,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, * depending on how authentication is working. Other codes * are definitely errors, so give up here. */ - if(data->state.resume_from && data->set.httpreq == HTTPREQ_GET && + if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET && k->httpcode == 416) { /* "Requested Range Not Satisfiable", just proceed and pretend this is no error */ diff --git a/lib/http2.c b/lib/http2.c index 7d56e2280..61990019e 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -2031,7 +2031,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, h2_pri_spec(conn->data, &pri_spec); - switch(conn->data->set.httpreq) { + switch(conn->data->state.httpreq) { case HTTPREQ_POST: case HTTPREQ_POST_FORM: case HTTPREQ_POST_MIME: diff --git a/lib/mqtt.c b/lib/mqtt.c index 43a3b6e53..d09aab4ee 100644 --- a/lib/mqtt.c +++ b/lib/mqtt.c @@ -591,7 +591,7 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done) if(result) break; - if(conn->data->set.httpreq == HTTPREQ_POST) { + if(conn->data->state.httpreq == HTTPREQ_POST) { result = mqtt_publish(conn); if(!result) { result = mqtt_disconnect(conn); diff --git a/lib/rtsp.c b/lib/rtsp.c index 9c86b6171..2a9c683c3 100644 --- a/lib/rtsp.c +++ b/lib/rtsp.c @@ -498,14 +498,14 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) if(data->set.upload) { putsize = data->state.infilesize; - data->set.httpreq = HTTPREQ_PUT; + data->state.httpreq = HTTPREQ_PUT; } else { postsize = (data->state.infilesize != -1)? data->state.infilesize: (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0); - data->set.httpreq = HTTPREQ_POST; + data->state.httpreq = HTTPREQ_POST; } if(putsize > 0 || postsize > 0) { @@ -543,7 +543,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) } else if(rtspreq == RTSPREQ_GET_PARAMETER) { /* Check for an empty GET_PARAMETER (heartbeat) request */ - data->set.httpreq = HTTPREQ_HEAD; + data->state.httpreq = HTTPREQ_HEAD; data->set.opt_no_body = TRUE; } } diff --git a/lib/setopt.c b/lib/setopt.c index fc914aa09..90edf6aa7 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -271,6 +271,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Do not include the body part in the output data stream. */ data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE; + if(data->set.opt_no_body) + /* in HTTP lingo, no body means using the HEAD request... */ + data->set.method = HTTPREQ_HEAD; break; case CURLOPT_FAILONERROR: /* @@ -292,13 +295,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE; if(data->set.upload) { /* If this is HTTP, PUT is what's needed to "upload" */ - data->set.httpreq = HTTPREQ_PUT; + data->set.method = HTTPREQ_PUT; data->set.opt_no_body = FALSE; /* this is implied */ } else /* In HTTP, the opposite of upload is GET (unless NOBODY is true as then this can be changed to HEAD later on) */ - data->set.httpreq = HTTPREQ_GET; + data->set.method = HTTPREQ_GET; break; case CURLOPT_REQUEST_TARGET: result = Curl_setstropt(&data->set.str[STRING_TARGET], @@ -516,11 +519,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) CURLOPT_POSTFIELDS isn't used and the POST data is read off the callback! */ if(va_arg(param, long)) { - data->set.httpreq = HTTPREQ_POST; + data->set.method = HTTPREQ_POST; data->set.opt_no_body = FALSE; /* this is implied */ } else - data->set.httpreq = HTTPREQ_GET; + data->set.method = HTTPREQ_GET; break; case CURLOPT_COPYPOSTFIELDS: @@ -567,7 +570,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) } data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS]; - data->set.httpreq = HTTPREQ_POST; + data->set.method = HTTPREQ_POST; break; case CURLOPT_POSTFIELDS: @@ -577,7 +580,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) data->set.postfields = va_arg(param, void *); /* Release old copied data. */ (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); - data->set.httpreq = HTTPREQ_POST; + data->set.method = HTTPREQ_POST; break; case CURLOPT_POSTFIELDSIZE: @@ -623,7 +626,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Set to make us do HTTP POST */ data->set.httppost = va_arg(param, struct curl_httppost *); - data->set.httpreq = HTTPREQ_POST_FORM; + data->set.method = HTTPREQ_POST_FORM; data->set.opt_no_body = FALSE; /* this is implied */ break; #endif /* CURL_DISABLE_HTTP */ @@ -635,7 +638,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) result = Curl_mime_set_subparts(&data->set.mimepost, va_arg(param, curl_mime *), FALSE); if(!result) { - data->set.httpreq = HTTPREQ_POST_MIME; + data->set.method = HTTPREQ_POST_MIME; data->set.opt_no_body = FALSE; /* this is implied */ } break; @@ -830,7 +833,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) * Set to force us do HTTP GET */ if(va_arg(param, long)) { - data->set.httpreq = HTTPREQ_GET; + data->set.method = HTTPREQ_GET; data->set.upload = FALSE; /* switch off upload */ data->set.opt_no_body = FALSE; /* this is implied */ } @@ -940,7 +943,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) va_arg(param, char *)); /* we don't set - data->set.httpreq = HTTPREQ_CUSTOM; + data->set.method = HTTPREQ_CUSTOM; here, we continue as if we were using the already set type and this just changes the actual request keyword */ break; diff --git a/lib/transfer.c b/lib/transfer.c index 319744985..133a4783c 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -433,8 +433,8 @@ CURLcode Curl_readrewind(struct connectdata *conn) } if(data->set.postfields) ; /* do nothing */ - else if(data->set.httpreq == HTTPREQ_POST_MIME || - data->set.httpreq == HTTPREQ_POST_FORM) { + else if(data->state.httpreq == HTTPREQ_POST_MIME || + data->state.httpreq == HTTPREQ_POST_FORM) { if(Curl_mime_rewind(mimepart)) { failf(data, "Cannot rewind mime/post data"); return CURLE_SEND_FAIL_REWIND; @@ -719,7 +719,7 @@ static CURLcode readwrite_data(struct Curl_easy *data, infof(data, "Ignoring the response-body\n"); } if(data->state.resume_from && !k->content_range && - (data->set.httpreq == HTTPREQ_GET) && + (data->state.httpreq == HTTPREQ_GET) && !k->ignorebody) { if(k->size == data->state.resume_from) { @@ -1449,6 +1449,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) } } + data->state.httpreq = data->set.method; data->change.url = data->set.str[STRING_SET_URL]; /* Init the SSL session ID cache here. We do it here since we want to do it @@ -1469,10 +1470,10 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) data->state.authproxy.want = data->set.proxyauth; Curl_safefree(data->info.wouldredirect); - if(data->set.httpreq == HTTPREQ_PUT) + if(data->state.httpreq == HTTPREQ_PUT) data->state.infilesize = data->set.filesize; - else if((data->set.httpreq != HTTPREQ_GET) && - (data->set.httpreq != HTTPREQ_HEAD)) { + else if((data->state.httpreq != HTTPREQ_GET) && + (data->state.httpreq != HTTPREQ_HEAD)) { data->state.infilesize = data->set.postfieldsize; if(data->set.postfields && (data->state.infilesize == -1)) data->state.infilesize = (curl_off_t)strlen(data->set.postfields); @@ -1683,12 +1684,12 @@ CURLcode Curl_follow(struct Curl_easy *data, * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and * can be overridden with CURLOPT_POSTREDIR. */ - if((data->set.httpreq == HTTPREQ_POST - || data->set.httpreq == HTTPREQ_POST_FORM - || data->set.httpreq == HTTPREQ_POST_MIME) + if((data->state.httpreq == HTTPREQ_POST + || data->state.httpreq == HTTPREQ_POST_FORM + || data->state.httpreq == HTTPREQ_POST_MIME) && !(data->set.keep_post & CURL_REDIR_POST_301)) { infof(data, "Switch from POST to GET\n"); - data->set.httpreq = HTTPREQ_GET; + data->state.httpreq = HTTPREQ_GET; } break; case 302: /* Found */ @@ -1708,12 +1709,12 @@ CURLcode Curl_follow(struct Curl_easy *data, * This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and * can be overridden with CURLOPT_POSTREDIR. */ - if((data->set.httpreq == HTTPREQ_POST - || data->set.httpreq == HTTPREQ_POST_FORM - || data->set.httpreq == HTTPREQ_POST_MIME) + if((data->state.httpreq == HTTPREQ_POST + || data->state.httpreq == HTTPREQ_POST_FORM + || data->state.httpreq == HTTPREQ_POST_MIME) && !(data->set.keep_post & CURL_REDIR_POST_302)) { infof(data, "Switch from POST to GET\n"); - data->set.httpreq = HTTPREQ_GET; + data->state.httpreq = HTTPREQ_GET; } break; @@ -1723,12 +1724,12 @@ CURLcode Curl_follow(struct Curl_easy *data, * method is POST and the user specified to keep it as POST. * https://github.com/curl/curl/issues/5237#issuecomment-614641049 */ - if(data->set.httpreq != HTTPREQ_GET && - ((data->set.httpreq != HTTPREQ_POST && - data->set.httpreq != HTTPREQ_POST_FORM && - data->set.httpreq != HTTPREQ_POST_MIME) || + if(data->state.httpreq != HTTPREQ_GET && + ((data->state.httpreq != HTTPREQ_POST && + data->state.httpreq != HTTPREQ_POST_FORM && + data->state.httpreq != HTTPREQ_POST_MIME) || !(data->set.keep_post & CURL_REDIR_POST_303))) { - data->set.httpreq = HTTPREQ_GET; + data->state.httpreq = HTTPREQ_GET; data->set.upload = false; infof(data, "Switch to %s\n", data->set.opt_no_body?"HEAD":"GET"); @@ -462,7 +462,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) set->postfieldsize = -1; /* unknown size */ set->maxredirs = -1; /* allow any amount by default */ - set->httpreq = HTTPREQ_GET; /* Default HTTP request */ + set->method = HTTPREQ_GET; /* Default HTTP request */ set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */ #ifndef CURL_DISABLE_FTP set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */ @@ -3992,17 +3992,9 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn) data->state.done = FALSE; /* *_done() is not called yet */ data->state.expect100header = FALSE; - if(data->set.opt_no_body) /* in HTTP lingo, no body means using the HEAD request... */ - data->set.httpreq = HTTPREQ_HEAD; - else if(HTTPREQ_HEAD == data->set.httpreq) - /* ... but if unset there really is no perfect method that is the - "opposite" of HEAD but in reality most people probably think GET - then. The important thing is that we can't let it remain HEAD if the - opt_no_body is set FALSE since then we'll behave wrong when getting - HTTP. */ - data->set.httpreq = HTTPREQ_GET; + data->state.httpreq = HTTPREQ_HEAD; k->start = Curl_now(); /* start time */ k->now = k->start; /* current time is now */ diff --git a/lib/urldata.h b/lib/urldata.h index db6af9d10..d3cc5356e 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1390,6 +1390,7 @@ struct UrlState { int stream_weight; CURLU *uh; /* URL handle for the current parsed URL */ struct urlpieces up; + Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */ #ifndef CURL_DISABLE_HTTP size_t trailers_bytes_sent; struct dynbuf trailers_buf; /* a buffer containing the compiled trailing @@ -1678,7 +1679,7 @@ struct UserDefined { the hostname and port to connect to */ curl_TimeCond timecondition; /* kind of time/date comparison */ time_t timevalue; /* what time to compare with */ - Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */ + Curl_HttpReq method; /* what kind of HTTP request (if any) is this */ long httpversion; /* when non-zero, a specific HTTP version requested to be used in the library's request(s) */ struct ssl_config_data ssl; /* user defined SSL stuff */ diff --git a/lib/vquic/ngtcp2.c b/lib/vquic/ngtcp2.c index 40bc0f3f0..eaff638b4 100644 --- a/lib/vquic/ngtcp2.c +++ b/lib/vquic/ngtcp2.c @@ -1558,7 +1558,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem, } } - switch(data->set.httpreq) { + switch(data->state.httpreq) { case HTTPREQ_POST: case HTTPREQ_POST_FORM: case HTTPREQ_POST_MIME: diff --git a/lib/vquic/quiche.c b/lib/vquic/quiche.c index 83815e037..f93e95ee1 100644 --- a/lib/vquic/quiche.c +++ b/lib/vquic/quiche.c @@ -734,7 +734,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem, } } - switch(data->set.httpreq) { + switch(data->state.httpreq) { case HTTPREQ_POST: case HTTPREQ_POST_FORM: case HTTPREQ_POST_MIME: diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index 0633ccb2f..7a048f01a 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -196,7 +196,7 @@ test1608 test1609 test1610 test1611 test1612 \ \ test1620 test1621 \ \ -test1630 test1631 test1632 \ +test1630 test1631 test1632 test1633 \ \ test1650 test1651 test1652 test1653 test1654 test1655 \ \ diff --git a/tests/data/test1633 b/tests/data/test1633 new file mode 100644 index 000000000..5d29ef139 --- /dev/null +++ b/tests/data/test1633 @@ -0,0 +1,97 @@ +<testcase> +<info> +<keywords> +HTTP +HTTP GET +</keywords> +</info> + +# +# Server-side +<reply> +<data> +HTTP/1.1 301 OK +Accept-Ranges: bytes +Content-Length: 0 +Connection: close +Location: /16330002 + +</data> +<data2> +HTTP/1.1 429 too many requests +Retry-After: 1 +Content-Length: 0 +Connection: close + +</data2> + +<datacheck> +HTTP/1.1 301 OK +Accept-Ranges: bytes +Content-Length: 0 +Connection: close +Location: /16330002 + +HTTP/1.1 429 too many requests +Retry-After: 1 +Content-Length: 0 +Connection: close + +HTTP/1.1 301 OK +Accept-Ranges: bytes +Content-Length: 0 +Connection: close +Location: /16330002 + +HTTP/1.1 429 too many requests +Retry-After: 1 +Content-Length: 0 +Connection: close + +</datacheck> +</reply> + +# +# Client-side +<client> +<server> +http +</server> + <name> +HTTP GET + </name> + <command> +http://%HOSTIP:%HTTPPORT/1633 -d moo --retry 1 -L +</command> +</client> + +# +# Verify data after the test has been "shot" +<verify> +<strip> +^User-Agent:.* +</strip> +<protocol> +POST /1633 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 3
+Content-Type: application/x-www-form-urlencoded
+
+mooGET /16330002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+POST /1633 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 3
+Content-Type: application/x-www-form-urlencoded
+
+mooGET /16330002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol> +</verify> +</testcase> |