summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/http.c24
-rw-r--r--lib/http2.c2
-rw-r--r--lib/mqtt.c2
-rw-r--r--lib/rtsp.c6
-rw-r--r--lib/setopt.c23
-rw-r--r--lib/transfer.c39
-rw-r--r--lib/url.c12
-rw-r--r--lib/urldata.h3
-rw-r--r--lib/vquic/ngtcp2.c2
-rw-r--r--lib/vquic/quiche.c2
-rw-r--r--tests/data/Makefile.inc2
-rw-r--r--tests/data/test163397
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");
diff --git a/lib/url.c b/lib/url.c
index adc9767db..524d968c2 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -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>