Skip to content

Commit

Permalink
urldata: let the HTTP method be in the set.* struct
Browse files Browse the repository at this point in the history
When the method is updated inside libcurl we must still not change the
method as set by the user as then repeated transfers with that same
handle might not execute the same operation anymore!

This fixes the libcurl part of #5462

Test 1633 added to verify.

Closes #5499
  • Loading branch information
bagder committed Jun 2, 2020
1 parent cba7062 commit 9c845be
Show file tree
Hide file tree
Showing 12 changed files with 154 additions and 60 deletions.
24 changes: 12 additions & 12 deletions lib/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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))
;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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 */
Expand Down
2 changes: 1 addition & 1 deletion lib/http2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion lib/mqtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions lib/rtsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
}
Expand Down
23 changes: 13 additions & 10 deletions lib/setopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
/*
Expand All @@ -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],
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand Down Expand Up @@ -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 */
Expand All @@ -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;
Expand Down Expand Up @@ -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 */
}
Expand Down Expand Up @@ -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;
Expand Down
39 changes: 20 additions & 19 deletions lib/transfer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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 */
Expand All @@ -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;

Expand All @@ -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");
Expand Down
12 changes: 2 additions & 10 deletions lib/url.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down
3 changes: 2 additions & 1 deletion lib/urldata.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */
Expand Down
2 changes: 1 addition & 1 deletion lib/vquic/ngtcp2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion lib/vquic/quiche.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion tests/data/Makefile.inc
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ test1608 test1609 test1610 test1611 test1612 \
\
test1620 test1621 \
\
test1630 test1631 test1632 \
test1630 test1631 test1632 test1633 \
\
test1650 test1651 test1652 test1653 test1654 test1655 \
\
Expand Down
Loading

0 comments on commit 9c845be

Please sign in to comment.