1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
23 #include "curl_setup.h"
25 #ifndef CURL_DISABLE_HTTP
27 #ifdef HAVE_NETINET_IN_H
28 #include <netinet/in.h>
34 #ifdef HAVE_ARPA_INET_H
35 #include <arpa/inet.h>
40 #ifdef HAVE_SYS_IOCTL_H
41 #include <sys/ioctl.h>
44 #ifdef HAVE_SYS_PARAM_H
45 #include <sys/param.h>
53 #include <curl/curl.h>
59 #include "curl_base64.h"
61 #include "vauth/vauth.h"
62 #include "vtls/vtls.h"
63 #include "http_digest.h"
64 #include "http_ntlm.h"
65 #include "curl_ntlm_wb.h"
66 #include "http_negotiate.h"
67 #include "http_aws_sigv4.h"
73 #include "parsedate.h" /* for the week day and month names */
74 #include "strtoofft.h"
77 #include "content_encoding.h"
78 #include "http_proxy.h"
87 /* The last 3 #include files should be in this order */
88 #include "curl_printf.h"
89 #include "curl_memory.h"
93 * Forward declarations.
96 static int http_getsock_do(struct Curl_easy *data,
97 struct connectdata *conn,
98 curl_socket_t *socks);
99 static bool http_should_fail(struct Curl_easy *data);
101 #ifndef CURL_DISABLE_PROXY
102 static CURLcode add_haproxy_protocol_header(struct Curl_easy *data);
106 static CURLcode https_connecting(struct Curl_easy *data, bool *done);
107 static int https_getsock(struct Curl_easy *data,
108 struct connectdata *conn,
109 curl_socket_t *socks);
111 #define https_connecting(x,y) CURLE_COULDNT_CONNECT
113 static CURLcode http_setup_conn(struct Curl_easy *data,
114 struct connectdata *conn);
117 * HTTP handler interface.
119 const struct Curl_handler Curl_handler_http = {
121 http_setup_conn, /* setup_connection */
122 Curl_http, /* do_it */
123 Curl_http_done, /* done */
124 ZERO_NULL, /* do_more */
125 Curl_http_connect, /* connect_it */
126 ZERO_NULL, /* connecting */
127 ZERO_NULL, /* doing */
128 ZERO_NULL, /* proto_getsock */
129 http_getsock_do, /* doing_getsock */
130 ZERO_NULL, /* domore_getsock */
131 ZERO_NULL, /* perform_getsock */
132 ZERO_NULL, /* disconnect */
133 ZERO_NULL, /* readwrite */
134 ZERO_NULL, /* connection_check */
135 ZERO_NULL, /* attach connection */
136 PORT_HTTP, /* defport */
137 CURLPROTO_HTTP, /* protocol */
138 CURLPROTO_HTTP, /* family */
139 PROTOPT_CREDSPERREQUEST | /* flags */
145 * HTTPS handler interface.
147 const struct Curl_handler Curl_handler_https = {
148 "HTTPS", /* scheme */
149 http_setup_conn, /* setup_connection */
150 Curl_http, /* do_it */
151 Curl_http_done, /* done */
152 ZERO_NULL, /* do_more */
153 Curl_http_connect, /* connect_it */
154 https_connecting, /* connecting */
155 ZERO_NULL, /* doing */
156 https_getsock, /* proto_getsock */
157 http_getsock_do, /* doing_getsock */
158 ZERO_NULL, /* domore_getsock */
159 ZERO_NULL, /* perform_getsock */
160 ZERO_NULL, /* disconnect */
161 ZERO_NULL, /* readwrite */
162 ZERO_NULL, /* connection_check */
163 ZERO_NULL, /* attach connection */
164 PORT_HTTPS, /* defport */
165 CURLPROTO_HTTPS, /* protocol */
166 CURLPROTO_HTTP, /* family */
167 PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN | /* flags */
172 static CURLcode http_setup_conn(struct Curl_easy *data,
173 struct connectdata *conn)
175 /* allocate the HTTP-specific struct for the Curl_easy, only to survive
176 during this request */
178 DEBUGASSERT(data->req.p.http == NULL);
180 http = calloc(1, sizeof(struct HTTP));
182 return CURLE_OUT_OF_MEMORY;
184 Curl_mime_initpart(&http->form, data);
185 data->req.p.http = http;
187 if(data->state.httpwant == CURL_HTTP_VERSION_3) {
188 if(conn->handler->flags & PROTOPT_SSL)
189 /* Only go HTTP/3 directly on HTTPS URLs. It needs a UDP socket and does
191 conn->transport = TRNSPRT_QUIC;
193 failf(data, "HTTP/3 requested for non-HTTPS URL");
194 return CURLE_URL_MALFORMAT;
198 if(!CONN_INUSE(conn))
199 /* if not already multi-using, setup connection details */
200 Curl_http2_setup_conn(conn);
201 Curl_http2_setup_req(data);
206 #ifndef CURL_DISABLE_PROXY
208 * checkProxyHeaders() checks the linked list of custom proxy headers
209 * if proxy headers are not available, then it will lookup into http header
212 * It takes a connectdata struct as input to see if this is a proxy request or
213 * not, as it then might check a different header list. Provide the header
214 * prefix without colon!
216 char *Curl_checkProxyheaders(struct Curl_easy *data,
217 const struct connectdata *conn,
218 const char *thisheader,
219 const size_t thislen)
221 struct curl_slist *head;
223 for(head = (conn->bits.proxy && data->set.sep_headers) ?
224 data->set.proxyheaders : data->set.headers;
225 head; head = head->next) {
226 if(strncasecompare(head->data, thisheader, thislen) &&
227 Curl_headersep(head->data[thislen]))
235 #define Curl_checkProxyheaders(x,y,z,a) NULL
239 * Strip off leading and trailing whitespace from the value in the
240 * given HTTP header line and return a strdupped copy. Returns NULL in
241 * case of allocation failure. Returns an empty string if the header value
242 * consists entirely of whitespace.
244 char *Curl_copy_header_value(const char *header)
251 /* Find the end of the header name */
252 while(*header && (*header != ':'))
256 /* Skip over colon */
259 /* Find the first non-space letter */
261 while(*start && ISSPACE(*start))
264 /* data is in the host encoding so
265 use '\r' and '\n' instead of 0x0d and 0x0a */
266 end = strchr(start, '\r');
268 end = strchr(start, '\n');
270 end = strchr(start, '\0');
274 /* skip all trailing space letters */
275 while((end > start) && ISSPACE(*end))
278 /* get length of the type */
279 len = end - start + 1;
281 value = malloc(len + 1);
285 memcpy(value, start, len);
286 value[len] = 0; /* null-terminate */
291 #ifndef CURL_DISABLE_HTTP_AUTH
293 * http_output_basic() sets up an Authorization: header (or the proxy version)
294 * for HTTP Basic authentication.
298 static CURLcode http_output_basic(struct Curl_easy *data, bool proxy)
301 char *authorization = NULL;
308 /* credentials are unique per transfer for HTTP, do not use the ones for the
311 #ifndef CURL_DISABLE_PROXY
312 userp = &data->state.aptr.proxyuserpwd;
313 user = data->state.aptr.proxyuser;
314 pwd = data->state.aptr.proxypasswd;
316 return CURLE_NOT_BUILT_IN;
320 userp = &data->state.aptr.userpwd;
321 user = data->state.aptr.user;
322 pwd = data->state.aptr.passwd;
325 out = aprintf("%s:%s", user ? user : "", pwd ? pwd : "");
327 return CURLE_OUT_OF_MEMORY;
329 result = Curl_base64_encode(out, strlen(out), &authorization, &size);
334 result = CURLE_REMOTE_ACCESS_DENIED;
339 *userp = aprintf("%sAuthorization: Basic %s\r\n",
340 proxy ? "Proxy-" : "",
344 result = CURLE_OUT_OF_MEMORY;
354 * http_output_bearer() sets up an Authorization: header
355 * for HTTP Bearer authentication.
359 static CURLcode http_output_bearer(struct Curl_easy *data)
362 CURLcode result = CURLE_OK;
364 userp = &data->state.aptr.userpwd;
366 *userp = aprintf("Authorization: Bearer %s\r\n",
367 data->set.str[STRING_BEARER]);
370 result = CURLE_OUT_OF_MEMORY;
380 /* pickoneauth() selects the most favourable authentication method from the
381 * ones available and the ones we want.
383 * return TRUE if one was picked
385 static bool pickoneauth(struct auth *pick, unsigned long mask)
388 /* only deal with authentication we want */
389 unsigned long avail = pick->avail & pick->want & mask;
392 /* The order of these checks is highly relevant, as this will be the order
393 of preference in case of the existence of multiple accepted types. */
394 if(avail & CURLAUTH_NEGOTIATE)
395 pick->picked = CURLAUTH_NEGOTIATE;
396 else if(avail & CURLAUTH_BEARER)
397 pick->picked = CURLAUTH_BEARER;
398 else if(avail & CURLAUTH_DIGEST)
399 pick->picked = CURLAUTH_DIGEST;
400 else if(avail & CURLAUTH_NTLM)
401 pick->picked = CURLAUTH_NTLM;
402 else if(avail & CURLAUTH_NTLM_WB)
403 pick->picked = CURLAUTH_NTLM_WB;
404 else if(avail & CURLAUTH_BASIC)
405 pick->picked = CURLAUTH_BASIC;
406 else if(avail & CURLAUTH_AWS_SIGV4)
407 pick->picked = CURLAUTH_AWS_SIGV4;
409 pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
412 pick->avail = CURLAUTH_NONE; /* clear it here */
418 * http_perhapsrewind()
420 * If we are doing POST or PUT {
421 * If we have more data to send {
422 * If we are doing NTLM {
423 * Keep sending since we must not disconnect
426 * If there is more than just a little data left to send, close
427 * the current connection by force.
430 * If we have sent any data {
431 * If we don't have track of all the data {
432 * call app to tell it to rewind
435 * rewind internally so that the operation can restart fine
440 static CURLcode http_perhapsrewind(struct Curl_easy *data,
441 struct connectdata *conn)
443 struct HTTP *http = data->req.p.http;
444 curl_off_t bytessent;
445 curl_off_t expectsend = -1; /* default is unknown */
448 /* If this is still NULL, we have not reach very far and we can safely
449 skip this rewinding stuff */
452 switch(data->state.httpreq) {
460 bytessent = data->req.writebytecount;
462 if(conn->bits.authneg) {
463 /* This is a state where we are known to be negotiating and we don't send
467 else if(!conn->bits.protoconnstart) {
468 /* HTTP CONNECT in progress: there is no body */
472 /* figure out how much data we are expected to send */
473 switch(data->state.httpreq) {
476 if(data->state.infilesize != -1)
477 expectsend = data->state.infilesize;
479 case HTTPREQ_POST_FORM:
480 case HTTPREQ_POST_MIME:
481 expectsend = http->postsize;
488 conn->bits.rewindaftersend = FALSE; /* default */
490 if((expectsend == -1) || (expectsend > bytessent)) {
491 #if defined(USE_NTLM)
492 /* There is still data left to send */
493 if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
494 (data->state.authhost.picked == CURLAUTH_NTLM) ||
495 (data->state.authproxy.picked == CURLAUTH_NTLM_WB) ||
496 (data->state.authhost.picked == CURLAUTH_NTLM_WB)) {
497 if(((expectsend - bytessent) < 2000) ||
498 (conn->http_ntlm_state != NTLMSTATE_NONE) ||
499 (conn->proxy_ntlm_state != NTLMSTATE_NONE)) {
500 /* The NTLM-negotiation has started *OR* there is just a little (<2K)
501 data left to send, keep on sending. */
503 /* rewind data when completely done sending! */
504 if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
505 conn->bits.rewindaftersend = TRUE;
506 infof(data, "Rewind stream after send");
513 /* this is already marked to get closed */
516 infof(data, "NTLM send, close instead of sending %"
517 CURL_FORMAT_CURL_OFF_T " bytes",
518 (curl_off_t)(expectsend - bytessent));
521 #if defined(USE_SPNEGO)
522 /* There is still data left to send */
523 if((data->state.authproxy.picked == CURLAUTH_NEGOTIATE) ||
524 (data->state.authhost.picked == CURLAUTH_NEGOTIATE)) {
525 if(((expectsend - bytessent) < 2000) ||
526 (conn->http_negotiate_state != GSS_AUTHNONE) ||
527 (conn->proxy_negotiate_state != GSS_AUTHNONE)) {
528 /* The NEGOTIATE-negotiation has started *OR*
529 there is just a little (<2K) data left to send, keep on sending. */
531 /* rewind data when completely done sending! */
532 if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
533 conn->bits.rewindaftersend = TRUE;
534 infof(data, "Rewind stream after send");
541 /* this is already marked to get closed */
544 infof(data, "NEGOTIATE send, close instead of sending %"
545 CURL_FORMAT_CURL_OFF_T " bytes",
546 (curl_off_t)(expectsend - bytessent));
550 /* This is not NEGOTIATE/NTLM or many bytes left to send: close */
551 streamclose(conn, "Mid-auth HTTP and much data left to send");
552 data->req.size = 0; /* don't download any more than 0 bytes */
554 /* There still is data left to send, but this connection is marked for
555 closure so we can safely do the rewind right now */
559 /* we rewind now at once since if we already sent something */
560 return Curl_readrewind(data);
566 * Curl_http_auth_act() gets called when all HTTP headers have been received
567 * and it checks what authentication methods that are available and decides
568 * which one (if any) to use. It will set 'newurl' if an auth method was
572 CURLcode Curl_http_auth_act(struct Curl_easy *data)
574 struct connectdata *conn = data->conn;
575 bool pickhost = FALSE;
576 bool pickproxy = FALSE;
577 CURLcode result = CURLE_OK;
578 unsigned long authmask = ~0ul;
580 if(!data->set.str[STRING_BEARER])
581 authmask &= (unsigned long)~CURLAUTH_BEARER;
583 if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
584 /* this is a transient response code, ignore */
587 if(data->state.authproblem)
588 return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
590 if((data->state.aptr.user || data->set.str[STRING_BEARER]) &&
591 ((data->req.httpcode == 401) ||
592 (conn->bits.authneg && data->req.httpcode < 300))) {
593 pickhost = pickoneauth(&data->state.authhost, authmask);
595 data->state.authproblem = TRUE;
596 if(data->state.authhost.picked == CURLAUTH_NTLM &&
597 conn->httpversion > 11) {
598 infof(data, "Forcing HTTP/1.1 for NTLM");
599 connclose(conn, "Force HTTP/1.1 connection");
600 data->state.httpwant = CURL_HTTP_VERSION_1_1;
603 #ifndef CURL_DISABLE_PROXY
604 if(conn->bits.proxy_user_passwd &&
605 ((data->req.httpcode == 407) ||
606 (conn->bits.authneg && data->req.httpcode < 300))) {
607 pickproxy = pickoneauth(&data->state.authproxy,
608 authmask & ~CURLAUTH_BEARER);
610 data->state.authproblem = TRUE;
614 if(pickhost || pickproxy) {
615 if((data->state.httpreq != HTTPREQ_GET) &&
616 (data->state.httpreq != HTTPREQ_HEAD) &&
617 !conn->bits.rewindaftersend) {
618 result = http_perhapsrewind(data, conn);
622 /* In case this is GSS auth, the newurl field is already allocated so
623 we must make sure to free it before allocating a new one. As figured
624 out in bug #2284386 */
625 Curl_safefree(data->req.newurl);
626 data->req.newurl = strdup(data->state.url); /* clone URL */
627 if(!data->req.newurl)
628 return CURLE_OUT_OF_MEMORY;
630 else if((data->req.httpcode < 300) &&
631 (!data->state.authhost.done) &&
632 conn->bits.authneg) {
633 /* no (known) authentication available,
634 authentication is not "done" yet and
635 no authentication seems to be required and
636 we didn't try HEAD or GET */
637 if((data->state.httpreq != HTTPREQ_GET) &&
638 (data->state.httpreq != HTTPREQ_HEAD)) {
639 data->req.newurl = strdup(data->state.url); /* clone URL */
640 if(!data->req.newurl)
641 return CURLE_OUT_OF_MEMORY;
642 data->state.authhost.done = TRUE;
645 if(http_should_fail(data)) {
646 failf(data, "The requested URL returned error: %d",
648 result = CURLE_HTTP_RETURNED_ERROR;
655 * Curl_allow_auth_to_host() tells if authentication, cookies or other
656 * "sensitive data" can (still) be sent to this host.
658 bool Curl_allow_auth_to_host(struct Curl_easy *data)
660 struct connectdata *conn = data->conn;
661 return (!data->state.this_is_a_follow ||
662 data->set.allow_auth_to_other_hosts ||
663 (data->state.first_host &&
664 strcasecompare(data->state.first_host, conn->host.name) &&
665 (data->state.first_remote_port == conn->remote_port) &&
666 (data->state.first_remote_protocol == conn->handler->protocol)));
669 #ifndef CURL_DISABLE_HTTP_AUTH
671 * Output the correct authentication header depending on the auth type
672 * and whether or not it is to a proxy.
675 output_auth_headers(struct Curl_easy *data,
676 struct connectdata *conn,
677 struct auth *authstatus,
682 const char *auth = NULL;
683 CURLcode result = CURLE_OK;
686 #ifdef CURL_DISABLE_CRYPTO_AUTH
690 #ifndef CURL_DISABLE_CRYPTO_AUTH
691 if(authstatus->picked == CURLAUTH_AWS_SIGV4) {
693 result = Curl_output_aws_sigv4(data, proxy);
700 if(authstatus->picked == CURLAUTH_NEGOTIATE) {
702 result = Curl_output_negotiate(data, conn, proxy);
709 if(authstatus->picked == CURLAUTH_NTLM) {
711 result = Curl_output_ntlm(data, proxy);
717 #if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
718 if(authstatus->picked == CURLAUTH_NTLM_WB) {
720 result = Curl_output_ntlm_wb(data, conn, proxy);
726 #ifndef CURL_DISABLE_CRYPTO_AUTH
727 if(authstatus->picked == CURLAUTH_DIGEST) {
729 result = Curl_output_digest(data,
731 (const unsigned char *)request,
732 (const unsigned char *)path);
738 if(authstatus->picked == CURLAUTH_BASIC) {
741 #ifndef CURL_DISABLE_PROXY
742 (proxy && conn->bits.proxy_user_passwd &&
743 !Curl_checkProxyheaders(data, conn, STRCONST("Proxy-authorization"))) ||
745 (!proxy && data->state.aptr.user &&
746 !Curl_checkheaders(data, STRCONST("Authorization")))) {
748 result = http_output_basic(data, proxy);
753 /* NOTE: this function should set 'done' TRUE, as the other auth
754 functions work that way */
755 authstatus->done = TRUE;
757 if(authstatus->picked == CURLAUTH_BEARER) {
759 if((!proxy && data->set.str[STRING_BEARER] &&
760 !Curl_checkheaders(data, STRCONST("Authorization")))) {
762 result = http_output_bearer(data);
767 /* NOTE: this function should set 'done' TRUE, as the other auth
768 functions work that way */
769 authstatus->done = TRUE;
773 #ifndef CURL_DISABLE_PROXY
774 infof(data, "%s auth using %s with user '%s'",
775 proxy ? "Proxy" : "Server", auth,
776 proxy ? (data->state.aptr.proxyuser ?
777 data->state.aptr.proxyuser : "") :
778 (data->state.aptr.user ?
779 data->state.aptr.user : ""));
781 infof(data, "Server auth using %s with user '%s'",
782 auth, data->state.aptr.user ?
783 data->state.aptr.user : "");
785 authstatus->multipass = (!authstatus->done) ? TRUE : FALSE;
788 authstatus->multipass = FALSE;
794 * Curl_http_output_auth() setups the authentication headers for the
795 * host/proxy and the correct authentication
796 * method. data->state.authdone is set to TRUE when authentication is
799 * @param conn all information about the current connection
800 * @param request pointer to the request keyword
801 * @param path pointer to the requested path; should include query part
802 * @param proxytunnel boolean if this is the request setting up a "proxy
808 Curl_http_output_auth(struct Curl_easy *data,
809 struct connectdata *conn,
811 Curl_HttpReq httpreq,
813 bool proxytunnel) /* TRUE if this is the request setting
814 up the proxy tunnel */
816 CURLcode result = CURLE_OK;
817 struct auth *authhost;
818 struct auth *authproxy;
822 authhost = &data->state.authhost;
823 authproxy = &data->state.authproxy;
826 #ifndef CURL_DISABLE_PROXY
827 (conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
829 data->state.aptr.user || data->set.str[STRING_BEARER])
830 /* continue please */;
832 authhost->done = TRUE;
833 authproxy->done = TRUE;
834 return CURLE_OK; /* no authentication with no user or password */
837 if(authhost->want && !authhost->picked)
838 /* The app has selected one or more methods, but none has been picked
839 so far by a server round-trip. Then we set the picked one to the
840 want one, and if this is one single bit it'll be used instantly. */
841 authhost->picked = authhost->want;
843 if(authproxy->want && !authproxy->picked)
844 /* The app has selected one or more methods, but none has been picked so
845 far by a proxy round-trip. Then we set the picked one to the want one,
846 and if this is one single bit it'll be used instantly. */
847 authproxy->picked = authproxy->want;
849 #ifndef CURL_DISABLE_PROXY
850 /* Send proxy authentication header if needed */
851 if(conn->bits.httpproxy &&
852 (conn->bits.tunnel_proxy == (bit)proxytunnel)) {
853 result = output_auth_headers(data, conn, authproxy, request, path, TRUE);
860 #endif /* CURL_DISABLE_PROXY */
861 /* we have no proxy so let's pretend we're done authenticating
863 authproxy->done = TRUE;
865 /* To prevent the user+password to get sent to other than the original host
866 due to a location-follow */
867 if(Curl_allow_auth_to_host(data)
868 #ifndef CURL_DISABLE_NETRC
872 result = output_auth_headers(data, conn, authhost, request, path, FALSE);
874 authhost->done = TRUE;
876 if(((authhost->multipass && !authhost->done) ||
877 (authproxy->multipass && !authproxy->done)) &&
878 (httpreq != HTTPREQ_GET) &&
879 (httpreq != HTTPREQ_HEAD)) {
880 /* Auth is required and we are not authenticated yet. Make a PUT or POST
881 with content-length zero as a "probe". */
882 conn->bits.authneg = TRUE;
885 conn->bits.authneg = FALSE;
893 Curl_http_output_auth(struct Curl_easy *data,
894 struct connectdata *conn,
896 Curl_HttpReq httpreq,
911 * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
912 * headers. They are dealt with both in the transfer.c main loop and in the
913 * proxy CONNECT loop.
916 static int is_valid_auth_separator(char ch)
918 return ch == '\0' || ch == ',' || ISSPACE(ch);
921 CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
922 const char *auth) /* the first non-space */
925 * This resource requires authentication
927 struct connectdata *conn = data->conn;
929 curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
930 &conn->http_negotiate_state;
932 unsigned long *availp;
935 (void) conn; /* In case conditionals make it unused. */
938 availp = &data->info.proxyauthavail;
939 authp = &data->state.authproxy;
942 availp = &data->info.httpauthavail;
943 authp = &data->state.authhost;
947 * Here we check if we want the specific single authentication (using ==) and
948 * if we do, we initiate usage of it.
950 * If the provided authentication is wanted as one out of several accepted
951 * types (using &), we OR this authentication type to the authavail
956 * ->picked is first set to the 'want' value (one or more bits) before the
957 * request is sent, and then it is again set _after_ all response 401/407
958 * headers have been received but then only to a single preferred method
964 if(checkprefix("Negotiate", auth) && is_valid_auth_separator(auth[9])) {
965 if((authp->avail & CURLAUTH_NEGOTIATE) ||
966 Curl_auth_is_spnego_supported()) {
967 *availp |= CURLAUTH_NEGOTIATE;
968 authp->avail |= CURLAUTH_NEGOTIATE;
970 if(authp->picked == CURLAUTH_NEGOTIATE) {
971 CURLcode result = Curl_input_negotiate(data, conn, proxy, auth);
973 DEBUGASSERT(!data->req.newurl);
974 data->req.newurl = strdup(data->state.url);
975 if(!data->req.newurl)
976 return CURLE_OUT_OF_MEMORY;
977 data->state.authproblem = FALSE;
978 /* we received a GSS auth token and we dealt with it fine */
979 *negstate = GSS_AUTHRECV;
982 data->state.authproblem = TRUE;
989 /* NTLM support requires the SSL crypto libs */
990 if(checkprefix("NTLM", auth) && is_valid_auth_separator(auth[4])) {
991 if((authp->avail & CURLAUTH_NTLM) ||
992 (authp->avail & CURLAUTH_NTLM_WB) ||
993 Curl_auth_is_ntlm_supported()) {
994 *availp |= CURLAUTH_NTLM;
995 authp->avail |= CURLAUTH_NTLM;
997 if(authp->picked == CURLAUTH_NTLM ||
998 authp->picked == CURLAUTH_NTLM_WB) {
999 /* NTLM authentication is picked and activated */
1000 CURLcode result = Curl_input_ntlm(data, proxy, auth);
1002 data->state.authproblem = FALSE;
1003 #ifdef NTLM_WB_ENABLED
1004 if(authp->picked == CURLAUTH_NTLM_WB) {
1005 *availp &= ~CURLAUTH_NTLM;
1006 authp->avail &= ~CURLAUTH_NTLM;
1007 *availp |= CURLAUTH_NTLM_WB;
1008 authp->avail |= CURLAUTH_NTLM_WB;
1010 result = Curl_input_ntlm_wb(data, conn, proxy, auth);
1012 infof(data, "Authentication problem. Ignoring this.");
1013 data->state.authproblem = TRUE;
1019 infof(data, "Authentication problem. Ignoring this.");
1020 data->state.authproblem = TRUE;
1027 #ifndef CURL_DISABLE_CRYPTO_AUTH
1028 if(checkprefix("Digest", auth) && is_valid_auth_separator(auth[6])) {
1029 if((authp->avail & CURLAUTH_DIGEST) != 0)
1030 infof(data, "Ignoring duplicate digest auth header.");
1031 else if(Curl_auth_is_digest_supported()) {
1034 *availp |= CURLAUTH_DIGEST;
1035 authp->avail |= CURLAUTH_DIGEST;
1037 /* We call this function on input Digest headers even if Digest
1038 * authentication isn't activated yet, as we need to store the
1039 * incoming data from this header in case we are going to use
1041 result = Curl_input_digest(data, proxy, auth);
1043 infof(data, "Authentication problem. Ignoring this.");
1044 data->state.authproblem = TRUE;
1050 if(checkprefix("Basic", auth) &&
1051 is_valid_auth_separator(auth[5])) {
1052 *availp |= CURLAUTH_BASIC;
1053 authp->avail |= CURLAUTH_BASIC;
1054 if(authp->picked == CURLAUTH_BASIC) {
1055 /* We asked for Basic authentication but got a 40X back
1056 anyway, which basically means our name+password isn't
1058 authp->avail = CURLAUTH_NONE;
1059 infof(data, "Authentication problem. Ignoring this.");
1060 data->state.authproblem = TRUE;
1064 if(checkprefix("Bearer", auth) &&
1065 is_valid_auth_separator(auth[6])) {
1066 *availp |= CURLAUTH_BEARER;
1067 authp->avail |= CURLAUTH_BEARER;
1068 if(authp->picked == CURLAUTH_BEARER) {
1069 /* We asked for Bearer authentication but got a 40X back
1070 anyway, which basically means our token isn't valid. */
1071 authp->avail = CURLAUTH_NONE;
1072 infof(data, "Authentication problem. Ignoring this.");
1073 data->state.authproblem = TRUE;
1077 /* there may be multiple methods on one line, so keep reading */
1078 while(*auth && *auth != ',') /* read up to the next comma */
1080 if(*auth == ',') /* if we're on a comma, skip it */
1082 while(*auth && ISSPACE(*auth))
1090 * http_should_fail() determines whether an HTTP response has gotten us
1091 * into an error state or not.
1093 * @param conn all information about the current connection
1095 * @retval FALSE communications should continue
1097 * @retval TRUE communications should not continue
1099 static bool http_should_fail(struct Curl_easy *data)
1103 DEBUGASSERT(data->conn);
1105 httpcode = data->req.httpcode;
1108 ** If we haven't been asked to fail on error,
1111 if(!data->set.http_fail_on_error)
1115 ** Any code < 400 is never terminal.
1121 ** A 416 response to a resume request is presumably because the file is
1122 ** already completely downloaded and thus not actually a fail.
1124 if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
1129 ** Any code >= 400 that's not 401 or 407 is always
1132 if((httpcode != 401) && (httpcode != 407))
1136 ** All we have left to deal with is 401 and 407
1138 DEBUGASSERT((httpcode == 401) || (httpcode == 407));
1141 ** Examine the current authentication state to see if this
1142 ** is an error. The idea is for this function to get
1143 ** called after processing all the headers in a response
1144 ** message. So, if we've been to asked to authenticate a
1145 ** particular stage, and we've done it, we're OK. But, if
1146 ** we're already completely authenticated, it's not OK to
1147 ** get another 401 or 407.
1149 ** It is possible for authentication to go stale such that
1150 ** the client needs to reauthenticate. Once that info is
1151 ** available, use it here.
1155 ** Either we're not authenticating, or we're supposed to
1156 ** be authenticating something else. This is an error.
1158 if((httpcode == 401) && !data->state.aptr.user)
1160 #ifndef CURL_DISABLE_PROXY
1161 if((httpcode == 407) && !data->conn->bits.proxy_user_passwd)
1165 return data->state.authproblem;
1169 * readmoredata() is a "fread() emulation" to provide POST and/or request
1170 * data. It is used when a huge POST is to be made and the entire chunk wasn't
1171 * sent in the first send(). This function will then be called from the
1172 * transfer.c loop when more data is to be sent to the peer.
1174 * Returns the amount of bytes it filled the buffer with.
1176 static size_t readmoredata(char *buffer,
1181 struct Curl_easy *data = (struct Curl_easy *)userp;
1182 struct HTTP *http = data->req.p.http;
1183 size_t fullsize = size * nitems;
1186 /* nothing to return */
1189 /* make sure that a HTTP request is never sent away chunked! */
1190 data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
1192 if(data->set.max_send_speed &&
1193 (data->set.max_send_speed < (curl_off_t)fullsize) &&
1194 (data->set.max_send_speed < http->postsize))
1196 fullsize = (size_t)data->set.max_send_speed;
1198 else if(http->postsize <= (curl_off_t)fullsize) {
1199 memcpy(buffer, http->postdata, (size_t)http->postsize);
1200 fullsize = (size_t)http->postsize;
1202 if(http->backup.postsize) {
1203 /* move backup data into focus and continue on that */
1204 http->postdata = http->backup.postdata;
1205 http->postsize = http->backup.postsize;
1206 data->state.fread_func = http->backup.fread_func;
1207 data->state.in = http->backup.fread_in;
1209 http->sending++; /* move one step up */
1211 http->backup.postsize = 0;
1219 memcpy(buffer, http->postdata, fullsize);
1220 http->postdata += fullsize;
1221 http->postsize -= fullsize;
1227 * Curl_buffer_send() sends a header buffer and frees all associated
1228 * memory. Body data may be appended to the header data if desired.
1232 CURLcode Curl_buffer_send(struct dynbuf *in,
1233 struct Curl_easy *data,
1234 /* add the number of sent bytes to this
1236 curl_off_t *bytes_written,
1237 /* how much of the buffer contains body data */
1238 curl_off_t included_body_bytes,
1245 struct connectdata *conn = data->conn;
1246 struct HTTP *http = data->req.p.http;
1248 curl_socket_t sockfd;
1251 DEBUGASSERT(socketindex <= SECONDARYSOCKET);
1253 sockfd = conn->sock[socketindex];
1255 /* The looping below is required since we use non-blocking sockets, but due
1256 to the circumstances we will just loop and try again and again etc */
1258 ptr = Curl_dyn_ptr(in);
1259 size = Curl_dyn_len(in);
1261 headersize = size - (size_t)included_body_bytes; /* the initial part that
1262 isn't body is header */
1264 DEBUGASSERT(size > (size_t)included_body_bytes);
1266 if((conn->handler->flags & PROTOPT_SSL
1267 #ifndef CURL_DISABLE_PROXY
1268 || conn->http_proxy.proxytype == CURLPROXY_HTTPS
1271 && conn->httpversion != 20) {
1272 /* Make sure this doesn't send more body bytes than what the max send
1273 speed says. The request bytes do not count to the max speed.
1275 if(data->set.max_send_speed &&
1276 (included_body_bytes > data->set.max_send_speed)) {
1277 curl_off_t overflow = included_body_bytes - data->set.max_send_speed;
1278 DEBUGASSERT((size_t)overflow < size);
1279 sendsize = size - (size_t)overflow;
1284 /* OpenSSL is very picky and we must send the SAME buffer pointer to the
1285 library when we attempt to re-send this buffer. Sending the same data
1286 is not enough, we must use the exact same address. For this reason, we
1287 must copy the data to the uploadbuffer first, since that is the buffer
1288 we will be using if this send is retried later.
1290 result = Curl_get_upload_buffer(data);
1292 /* malloc failed, free memory and return to the caller */
1296 /* We never send more than upload_buffer_size bytes in one single chunk
1297 when we speak HTTPS, as if only a fraction of it is sent now, this data
1298 needs to fit into the normal read-callback buffer later on and that
1299 buffer is using this size.
1301 if(sendsize > (size_t)data->set.upload_buffer_size)
1302 sendsize = (size_t)data->set.upload_buffer_size;
1304 memcpy(data->state.ulbuf, ptr, sendsize);
1305 ptr = data->state.ulbuf;
1309 /* Allow debug builds to override this logic to force short initial
1312 char *p = getenv("CURL_SMALLREQSEND");
1314 size_t altsize = (size_t)strtoul(p, NULL, 10);
1316 sendsize = CURLMIN(size, altsize);
1323 /* Make sure this doesn't send more body bytes than what the max send
1324 speed says. The request bytes do not count to the max speed.
1326 if(data->set.max_send_speed &&
1327 (included_body_bytes > data->set.max_send_speed)) {
1328 curl_off_t overflow = included_body_bytes - data->set.max_send_speed;
1329 DEBUGASSERT((size_t)overflow < size);
1330 sendsize = size - (size_t)overflow;
1337 result = Curl_write(data, sockfd, ptr, sendsize, &amount);
1341 * Note that we may not send the entire chunk at once, and we have a set
1342 * number of data bytes at the end of the big buffer (out of which we may
1343 * only send away a part).
1345 /* how much of the header that was sent */
1346 size_t headlen = (size_t)amount>headersize ? headersize : (size_t)amount;
1347 size_t bodylen = amount - headlen;
1349 /* this data _may_ contain binary stuff */
1350 Curl_debug(data, CURLINFO_HEADER_OUT, ptr, headlen);
1352 /* there was body data sent beyond the initial header part, pass that on
1353 to the debug callback too */
1354 Curl_debug(data, CURLINFO_DATA_OUT, ptr + headlen, bodylen);
1356 /* 'amount' can never be a very large value here so typecasting it so a
1357 signed 31 bit value should not cause problems even if ssize_t is
1359 *bytes_written += (long)amount;
1362 /* if we sent a piece of the body here, up the byte counter for it
1364 data->req.writebytecount += bodylen;
1365 Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
1367 if((size_t)amount != size) {
1368 /* The whole request could not be sent in one system call. We must
1369 queue it up and send it later when we get the chance. We must not
1370 loop here and wait until it might work again. */
1374 ptr = Curl_dyn_ptr(in) + amount;
1376 /* backup the currently set pointers */
1377 http->backup.fread_func = data->state.fread_func;
1378 http->backup.fread_in = data->state.in;
1379 http->backup.postdata = http->postdata;
1380 http->backup.postsize = http->postsize;
1382 /* set the new pointers for the request-sending */
1383 data->state.fread_func = (curl_read_callback)readmoredata;
1384 data->state.in = (void *)data;
1385 http->postdata = ptr;
1386 http->postsize = (curl_off_t)size;
1388 /* this much data is remaining header: */
1389 data->req.pendingheader = headersize - headlen;
1391 http->send_buffer = *in; /* copy the whole struct */
1392 http->sending = HTTPSEND_REQUEST;
1396 http->sending = HTTPSEND_BODY;
1397 /* the full buffer was sent, clean up and return */
1400 if((size_t)amount != size)
1401 /* We have no continue-send mechanism now, fail. This can only happen
1402 when this function is used from the CONNECT sending function. We
1403 currently (stupidly) assume that the whole request is always sent
1404 away in the first single chunk.
1408 return CURLE_SEND_ERROR;
1413 /* no remaining header data */
1414 data->req.pendingheader = 0;
1418 /* end of the add_buffer functions */
1419 /* ------------------------------------------------------------------------- */
1424 * Curl_compareheader()
1426 * Returns TRUE if 'headerline' contains the 'header' with given 'content'.
1427 * Pass headers WITH the colon.
1430 Curl_compareheader(const char *headerline, /* line to check */
1431 const char *header, /* header keyword _with_ colon */
1432 const size_t hlen, /* len of the keyword in bytes */
1433 const char *content, /* content string to find */
1434 const size_t clen) /* len of the content in bytes */
1436 /* RFC2616, section 4.2 says: "Each header field consists of a name followed
1437 * by a colon (":") and the field value. Field names are case-insensitive.
1438 * The field value MAY be preceded by any amount of LWS, though a single SP
1446 DEBUGASSERT(header);
1447 DEBUGASSERT(content);
1449 if(!strncasecompare(headerline, header, hlen))
1450 return FALSE; /* doesn't start with header */
1452 /* pass the header */
1453 start = &headerline[hlen];
1455 /* pass all whitespace */
1456 while(*start && ISSPACE(*start))
1459 /* find the end of the header line */
1460 end = strchr(start, '\r'); /* lines end with CRLF */
1462 /* in case there's a non-standard compliant line here */
1463 end = strchr(start, '\n');
1466 /* hm, there's no line ending here, use the zero byte! */
1467 end = strchr(start, '\0');
1470 len = end-start; /* length of the content part of the input line */
1472 /* find the content string in the rest of the line */
1473 for(; len >= clen; len--, start++) {
1474 if(strncasecompare(start, content, clen))
1475 return TRUE; /* match! */
1478 return FALSE; /* no match */
1482 * Curl_http_connect() performs HTTP stuff to do at connect-time, called from
1483 * the generic Curl_connect().
1485 CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
1488 struct connectdata *conn = data->conn;
1490 /* We default to persistent connections. We set this already in this connect
1491 function to make the re-use checks properly be able to check this bit. */
1492 connkeep(conn, "HTTP default");
1494 #ifndef CURL_DISABLE_PROXY
1495 /* the CONNECT procedure might not have been completed */
1496 result = Curl_proxy_connect(data, FIRSTSOCKET);
1500 if(conn->bits.proxy_connect_closed)
1501 /* this is not an error, just part of the connection negotiation */
1504 if(CONNECT_FIRSTSOCKET_PROXY_SSL())
1505 return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */
1507 if(Curl_connect_ongoing(conn))
1508 /* nothing else to do except wait right now - we're not done here. */
1511 if(data->set.haproxyprotocol) {
1512 /* add HAProxy PROXY protocol header */
1513 result = add_haproxy_protocol_header(data);
1519 if(conn->given->protocol & CURLPROTO_HTTPS) {
1520 /* perform SSL initialization */
1521 result = https_connecting(data, done);
1531 /* this returns the socket to wait for in the DO and DOING state for the multi
1532 interface and then we're always _sending_ a request and thus we wait for
1533 the single socket to become writable only */
1534 static int http_getsock_do(struct Curl_easy *data,
1535 struct connectdata *conn,
1536 curl_socket_t *socks)
1540 socks[0] = conn->sock[FIRSTSOCKET];
1541 return GETSOCK_WRITESOCK(0);
1544 #ifndef CURL_DISABLE_PROXY
1545 static CURLcode add_haproxy_protocol_header(struct Curl_easy *data)
1549 const char *tcp_version;
1550 DEBUGASSERT(data->conn);
1551 Curl_dyn_init(&req, DYN_HAXPROXY);
1553 #ifdef USE_UNIX_SOCKETS
1554 if(data->conn->unix_domain_socket)
1555 /* the buffer is large enough to hold this! */
1556 result = Curl_dyn_addn(&req, STRCONST("PROXY UNKNOWN\r\n"));
1559 /* Emit the correct prefix for IPv6 */
1560 tcp_version = data->conn->bits.ipv6 ? "TCP6" : "TCP4";
1562 result = Curl_dyn_addf(&req, "PROXY %s %s %s %i %i\r\n",
1564 data->info.conn_local_ip,
1565 data->info.conn_primary_ip,
1566 data->info.conn_local_port,
1567 data->info.conn_primary_port);
1569 #ifdef USE_UNIX_SOCKETS
1574 result = Curl_buffer_send(&req, data, &data->info.request_size,
1581 static CURLcode https_connecting(struct Curl_easy *data, bool *done)
1584 struct connectdata *conn = data->conn;
1585 DEBUGASSERT((data) && (data->conn->handler->flags & PROTOPT_SSL));
1588 if(conn->transport == TRNSPRT_QUIC) {
1594 /* perform SSL initialization for this socket */
1595 result = Curl_ssl_connect_nonblocking(data, conn, FALSE, FIRSTSOCKET, done);
1597 connclose(conn, "Failed HTTPS connection");
1602 static int https_getsock(struct Curl_easy *data,
1603 struct connectdata *conn,
1604 curl_socket_t *socks)
1607 if(conn->handler->flags & PROTOPT_SSL)
1608 return Curl_ssl->getsock(conn, socks);
1609 return GETSOCK_BLANK;
1611 #endif /* USE_SSL */
1614 * Curl_http_done() gets called after a single HTTP request has been
1618 CURLcode Curl_http_done(struct Curl_easy *data,
1619 CURLcode status, bool premature)
1621 struct connectdata *conn = data->conn;
1622 struct HTTP *http = data->req.p.http;
1624 /* Clear multipass flag. If authentication isn't done yet, then it will get
1625 * a chance to be set back to true when we output the next auth header */
1626 data->state.authhost.multipass = FALSE;
1627 data->state.authproxy.multipass = FALSE;
1629 Curl_unencode_cleanup(data);
1631 /* set the proper values (possibly modified on POST) */
1632 conn->seek_func = data->set.seek_func; /* restore */
1633 conn->seek_client = data->set.seek_client; /* restore */
1638 Curl_dyn_free(&http->send_buffer);
1639 Curl_http2_done(data, premature);
1640 Curl_quic_done(data, premature);
1641 Curl_mime_cleanpart(&http->form);
1642 Curl_dyn_reset(&data->state.headerb);
1643 Curl_hyper_done(data);
1648 if(!premature && /* this check is pointless when DONE is called before the
1649 entire operation is complete */
1650 !conn->bits.retry &&
1651 !data->set.connect_only &&
1652 (data->req.bytecount +
1653 data->req.headerbytecount -
1654 data->req.deductheadercount) <= 0) {
1655 /* If this connection isn't simply closed to be retried, AND nothing was
1656 read from the HTTP server (that counts), this can't be right so we
1657 return an error here */
1658 failf(data, "Empty reply from server");
1659 /* Mark it as closed to avoid the "left intact" message */
1660 streamclose(conn, "Empty reply from server");
1661 return CURLE_GOT_NOTHING;
1668 * Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
1669 * to avoid it include:
1671 * - if the user specifically requested HTTP 1.0
1672 * - if the server we are connected to only supports 1.0
1673 * - if any server previously contacted to handle this request only supports
1676 bool Curl_use_http_1_1plus(const struct Curl_easy *data,
1677 const struct connectdata *conn)
1679 if((data->state.httpversion == 10) || (conn->httpversion == 10))
1681 if((data->state.httpwant == CURL_HTTP_VERSION_1_0) &&
1682 (conn->httpversion <= 10))
1684 return ((data->state.httpwant == CURL_HTTP_VERSION_NONE) ||
1685 (data->state.httpwant >= CURL_HTTP_VERSION_1_1));
1689 static const char *get_http_string(const struct Curl_easy *data,
1690 const struct connectdata *conn)
1693 if((data->state.httpwant == CURL_HTTP_VERSION_3) ||
1694 (conn->httpversion == 30))
1699 if(conn->proto.httpc.h2)
1703 if(Curl_use_http_1_1plus(data, conn))
1710 /* check and possibly add an Expect: header */
1711 static CURLcode expect100(struct Curl_easy *data,
1712 struct connectdata *conn,
1715 CURLcode result = CURLE_OK;
1716 data->state.expect100header = FALSE; /* default to false unless it is set
1718 if(!data->state.disableexpect && Curl_use_http_1_1plus(data, conn) &&
1719 (conn->httpversion < 20)) {
1720 /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
1721 Expect: 100-continue to the headers which actually speeds up post
1722 operations (as there is one packet coming back from the web server) */
1723 const char *ptr = Curl_checkheaders(data, STRCONST("Expect"));
1725 data->state.expect100header =
1726 Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
1729 result = Curl_dyn_addn(req, STRCONST("Expect: 100-continue\r\n"));
1731 data->state.expect100header = TRUE;
1739 HEADER_SERVER, /* direct to server */
1740 HEADER_PROXY, /* regular request to proxy */
1741 HEADER_CONNECT /* sending CONNECT to a proxy */
1744 /* used to compile the provided trailers into one buffer
1745 will return an error code if one of the headers is
1746 not formatted correctly */
1747 CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
1749 struct Curl_easy *handle)
1752 CURLcode result = CURLE_OK;
1753 const char *endofline_native = NULL;
1754 const char *endofline_network = NULL;
1757 #ifdef CURL_DO_LINEEND_CONV
1758 (handle->state.prefer_ascii) ||
1760 (handle->set.crlf)) {
1761 /* \n will become \r\n later on */
1762 endofline_native = "\n";
1763 endofline_network = "\x0a";
1766 endofline_native = "\r\n";
1767 endofline_network = "\x0d\x0a";
1771 /* only add correctly formatted trailers */
1772 ptr = strchr(trailers->data, ':');
1773 if(ptr && *(ptr + 1) == ' ') {
1774 result = Curl_dyn_add(b, trailers->data);
1777 result = Curl_dyn_add(b, endofline_native);
1782 infof(handle, "Malformatted trailing header, skipping trailer");
1783 trailers = trailers->next;
1785 result = Curl_dyn_add(b, endofline_network);
1789 CURLcode Curl_add_custom_headers(struct Curl_easy *data,
1798 struct connectdata *conn = data->conn;
1800 struct curl_slist *h[2];
1801 struct curl_slist *headers;
1802 int numlists = 1; /* by default */
1805 #ifndef CURL_DISABLE_PROXY
1806 enum proxy_use proxy;
1809 proxy = HEADER_CONNECT;
1811 proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy?
1812 HEADER_PROXY:HEADER_SERVER;
1816 h[0] = data->set.headers;
1819 h[0] = data->set.headers;
1820 if(data->set.sep_headers) {
1821 h[1] = data->set.proxyheaders;
1825 case HEADER_CONNECT:
1826 if(data->set.sep_headers)
1827 h[0] = data->set.proxyheaders;
1829 h[0] = data->set.headers;
1834 h[0] = data->set.headers;
1837 /* loop through one or two lists */
1838 for(i = 0; i < numlists; i++) {
1842 char *semicolonp = NULL;
1843 ptr = strchr(headers->data, ':');
1846 /* no colon, semicolon? */
1847 ptr = strchr(headers->data, ';');
1850 ptr++; /* pass the semicolon */
1851 while(*ptr && ISSPACE(*ptr))
1855 /* this may be used for something else in the future */
1859 if(*(--ptr) == ';') {
1860 /* copy the source */
1861 semicolonp = strdup(headers->data);
1866 return CURLE_OUT_OF_MEMORY;
1868 /* put a colon where the semicolon is */
1869 semicolonp[ptr - headers->data] = ':';
1870 /* point at the colon */
1871 optr = &semicolonp [ptr - headers->data];
1877 if(ptr && (ptr != headers->data)) {
1878 /* we require a colon for this to be a true header */
1880 ptr++; /* pass the colon */
1881 while(*ptr && ISSPACE(*ptr))
1884 if(*ptr || semicolonp) {
1885 /* only send this if the contents was non-blank or done special */
1886 CURLcode result = CURLE_OK;
1887 char *compare = semicolonp ? semicolonp : headers->data;
1889 if(data->state.aptr.host &&
1890 /* a Host: header was sent already, don't pass on any custom Host:
1891 header as that will produce *two* in the same request! */
1892 checkprefix("Host:", compare))
1894 else if(data->state.httpreq == HTTPREQ_POST_FORM &&
1895 /* this header (extended by formdata.c) is sent later */
1896 checkprefix("Content-Type:", compare))
1898 else if(data->state.httpreq == HTTPREQ_POST_MIME &&
1899 /* this header is sent later */
1900 checkprefix("Content-Type:", compare))
1902 else if(conn->bits.authneg &&
1903 /* while doing auth neg, don't allow the custom length since
1904 we will force length zero then */
1905 checkprefix("Content-Length:", compare))
1907 else if(data->state.aptr.te &&
1908 /* when asking for Transfer-Encoding, don't pass on a custom
1910 checkprefix("Connection:", compare))
1912 else if((conn->httpversion >= 20) &&
1913 checkprefix("Transfer-Encoding:", compare))
1914 /* HTTP/2 doesn't support chunked requests */
1916 else if((checkprefix("Authorization:", compare) ||
1917 checkprefix("Cookie:", compare)) &&
1918 /* be careful of sending this potentially sensitive header to
1920 !Curl_allow_auth_to_host(data))
1924 result = Curl_hyper_header(data, req, compare);
1926 result = Curl_dyn_addf(req, "%s\r\n", compare);
1935 headers = headers->next;
1942 #ifndef CURL_DISABLE_PARSEDATE
1943 CURLcode Curl_add_timecondition(struct Curl_easy *data,
1951 const struct tm *tm;
1958 if(data->set.timecondition == CURL_TIMECOND_NONE)
1959 /* no condition was asked for */
1962 result = Curl_gmtime(data->set.timevalue, &keeptime);
1964 failf(data, "Invalid TIMEVALUE");
1969 switch(data->set.timecondition) {
1971 return CURLE_BAD_FUNCTION_ARGUMENT;
1973 case CURL_TIMECOND_IFMODSINCE:
1974 condp = "If-Modified-Since";
1977 case CURL_TIMECOND_IFUNMODSINCE:
1978 condp = "If-Unmodified-Since";
1981 case CURL_TIMECOND_LASTMOD:
1982 condp = "Last-Modified";
1987 if(Curl_checkheaders(data, condp, len)) {
1988 /* A custom header was specified; it will be sent instead. */
1992 /* The If-Modified-Since header family should have their times set in
1993 * GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
1994 * represented in Greenwich Mean Time (GMT), without exception. For the
1995 * purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal
1996 * Time)." (see page 20 of RFC2616).
1999 /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
2000 msnprintf(datestr, sizeof(datestr),
2001 "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
2003 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
2005 Curl_month[tm->tm_mon],
2012 result = Curl_dyn_add(req, datestr);
2014 result = Curl_hyper_header(data, req, datestr);
2021 CURLcode Curl_add_timecondition(struct Curl_easy *data,
2030 void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
2031 const char **method, Curl_HttpReq *reqp)
2033 Curl_HttpReq httpreq = data->state.httpreq;
2034 const char *request;
2035 if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
2037 httpreq = HTTPREQ_PUT;
2039 /* Now set the 'request' pointer to the proper request string */
2040 if(data->set.str[STRING_CUSTOMREQUEST])
2041 request = data->set.str[STRING_CUSTOMREQUEST];
2043 if(data->set.opt_no_body)
2046 DEBUGASSERT((httpreq >= HTTPREQ_GET) && (httpreq <= HTTPREQ_HEAD));
2049 case HTTPREQ_POST_FORM:
2050 case HTTPREQ_POST_MIME:
2056 default: /* this should never happen */
2070 CURLcode Curl_http_useragent(struct Curl_easy *data)
2072 /* The User-Agent string might have been allocated in url.c already, because
2073 it might have been used in the proxy connect, but if we have got a header
2074 with the user-agent string specified, we erase the previously made string
2076 if(Curl_checkheaders(data, STRCONST("User-Agent"))) {
2077 free(data->state.aptr.uagent);
2078 data->state.aptr.uagent = NULL;
2084 CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)
2087 if(!data->state.this_is_a_follow) {
2088 /* Free to avoid leaking memory on multiple requests*/
2089 free(data->state.first_host);
2091 data->state.first_host = strdup(conn->host.name);
2092 if(!data->state.first_host)
2093 return CURLE_OUT_OF_MEMORY;
2095 data->state.first_remote_port = conn->remote_port;
2096 data->state.first_remote_protocol = conn->handler->protocol;
2098 Curl_safefree(data->state.aptr.host);
2100 ptr = Curl_checkheaders(data, STRCONST("Host"));
2101 if(ptr && (!data->state.this_is_a_follow ||
2102 strcasecompare(data->state.first_host, conn->host.name))) {
2103 #if !defined(CURL_DISABLE_COOKIES)
2104 /* If we have a given custom Host: header, we extract the host name in
2105 order to possibly use it for cookie reasons later on. We only allow the
2106 custom Host: header if this is NOT a redirect, as setting Host: in the
2107 redirected request is being out on thin ice. Except if the host name
2108 is the same as the first one! */
2109 char *cookiehost = Curl_copy_header_value(ptr);
2111 return CURLE_OUT_OF_MEMORY;
2113 /* ignore empty data */
2116 /* If the host begins with '[', we start searching for the port after
2117 the bracket has been closed */
2118 if(*cookiehost == '[') {
2119 char *closingbracket;
2120 /* since the 'cookiehost' is an allocated memory area that will be
2121 freed later we cannot simply increment the pointer */
2122 memmove(cookiehost, cookiehost + 1, strlen(cookiehost) - 1);
2123 closingbracket = strchr(cookiehost, ']');
2125 *closingbracket = 0;
2128 int startsearch = 0;
2129 char *colon = strchr(cookiehost + startsearch, ':');
2131 *colon = 0; /* The host must not include an embedded port number */
2133 Curl_safefree(data->state.aptr.cookiehost);
2134 data->state.aptr.cookiehost = cookiehost;
2138 if(strcmp("Host:", ptr)) {
2139 data->state.aptr.host = aprintf("Host:%s\r\n", &ptr[5]);
2140 if(!data->state.aptr.host)
2141 return CURLE_OUT_OF_MEMORY;
2144 /* when clearing the header */
2145 data->state.aptr.host = NULL;
2148 /* When building Host: headers, we must put the host name within
2149 [brackets] if the host name is a plain IPv6-address. RFC2732-style. */
2150 const char *host = conn->host.name;
2152 if(((conn->given->protocol&CURLPROTO_HTTPS) &&
2153 (conn->remote_port == PORT_HTTPS)) ||
2154 ((conn->given->protocol&CURLPROTO_HTTP) &&
2155 (conn->remote_port == PORT_HTTP)) )
2156 /* if(HTTPS on port 443) OR (HTTP on port 80) then don't include
2157 the port number in the host string */
2158 data->state.aptr.host = aprintf("Host: %s%s%s\r\n",
2159 conn->bits.ipv6_ip?"[":"",
2161 conn->bits.ipv6_ip?"]":"");
2163 data->state.aptr.host = aprintf("Host: %s%s%s:%d\r\n",
2164 conn->bits.ipv6_ip?"[":"",
2166 conn->bits.ipv6_ip?"]":"",
2169 if(!data->state.aptr.host)
2170 /* without Host: we can't make a nice request */
2171 return CURLE_OUT_OF_MEMORY;
2177 * Append the request-target to the HTTP request
2179 CURLcode Curl_http_target(struct Curl_easy *data,
2180 struct connectdata *conn,
2183 CURLcode result = CURLE_OK;
2184 const char *path = data->state.up.path;
2185 const char *query = data->state.up.query;
2187 if(data->set.str[STRING_TARGET]) {
2188 path = data->set.str[STRING_TARGET];
2192 #ifndef CURL_DISABLE_PROXY
2193 if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
2194 /* Using a proxy but does not tunnel through it */
2196 /* The path sent to the proxy is in fact the entire URL. But if the remote
2197 host is a IDN-name, we must make sure that the request we produce only
2198 uses the encoded host name! */
2200 /* and no fragment part */
2203 CURLU *h = curl_url_dup(data->state.uh);
2205 return CURLE_OUT_OF_MEMORY;
2207 if(conn->host.dispname != conn->host.name) {
2208 uc = curl_url_set(h, CURLUPART_HOST, conn->host.name, 0);
2210 curl_url_cleanup(h);
2211 return CURLE_OUT_OF_MEMORY;
2214 uc = curl_url_set(h, CURLUPART_FRAGMENT, NULL, 0);
2216 curl_url_cleanup(h);
2217 return CURLE_OUT_OF_MEMORY;
2220 if(strcasecompare("http", data->state.up.scheme)) {
2221 /* when getting HTTP, we don't want the userinfo the URL */
2222 uc = curl_url_set(h, CURLUPART_USER, NULL, 0);
2224 curl_url_cleanup(h);
2225 return CURLE_OUT_OF_MEMORY;
2227 uc = curl_url_set(h, CURLUPART_PASSWORD, NULL, 0);
2229 curl_url_cleanup(h);
2230 return CURLE_OUT_OF_MEMORY;
2233 /* Extract the URL to use in the request. Store in STRING_TEMP_URL for
2234 clean-up reasons if the function returns before the free() further
2236 uc = curl_url_get(h, CURLUPART_URL, &url, CURLU_NO_DEFAULT_PORT);
2238 curl_url_cleanup(h);
2239 return CURLE_OUT_OF_MEMORY;
2242 curl_url_cleanup(h);
2245 result = Curl_dyn_add(r, data->set.str[STRING_TARGET]?
2246 data->set.str[STRING_TARGET]:url);
2251 if(strcasecompare("ftp", data->state.up.scheme)) {
2252 if(data->set.proxy_transfer_mode) {
2253 /* when doing ftp, append ;type=<a|i> if not present */
2254 char *type = strstr(path, ";type=");
2255 if(type && type[6] && type[7] == 0) {
2256 switch(Curl_raw_toupper(type[6])) {
2266 result = Curl_dyn_addf(r, ";type=%c",
2267 data->state.prefer_ascii ? 'a' : 'i');
2277 (void)conn; /* not used in disabled-proxy builds */
2280 result = Curl_dyn_add(r, path);
2284 result = Curl_dyn_addf(r, "?%s", query);
2290 CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
2291 Curl_HttpReq httpreq, const char **tep)
2293 CURLcode result = CURLE_OK;
2295 struct HTTP *http = data->req.p.http;
2299 case HTTPREQ_POST_MIME:
2300 http->sendit = &data->set.mimepost;
2302 case HTTPREQ_POST_FORM:
2303 /* Convert the form structure into a mime structure. */
2304 Curl_mime_cleanpart(&http->form);
2305 result = Curl_getformdata(data, &http->form, data->set.httppost,
2306 data->state.fread_func);
2309 http->sendit = &http->form;
2312 http->sendit = NULL;
2315 #ifndef CURL_DISABLE_MIME
2317 const char *cthdr = Curl_checkheaders(data, STRCONST("Content-Type"));
2319 /* Read and seek body only. */
2320 http->sendit->flags |= MIME_BODY_ONLY;
2322 /* Prepare the mime structure headers & set content type. */
2325 for(cthdr += 13; *cthdr == ' '; cthdr++)
2327 else if(http->sendit->kind == MIMEKIND_MULTIPART)
2328 cthdr = "multipart/form-data";
2330 curl_mime_headers(http->sendit, data->set.headers, 0);
2331 result = Curl_mime_prepare_headers(http->sendit, cthdr,
2332 NULL, MIMESTRATEGY_FORM);
2333 curl_mime_headers(http->sendit, NULL, 0);
2335 result = Curl_mime_rewind(http->sendit);
2338 http->postsize = Curl_mime_size(http->sendit);
2342 ptr = Curl_checkheaders(data, STRCONST("Transfer-Encoding"));
2344 /* Some kind of TE is requested, check if 'chunked' is chosen */
2345 data->req.upload_chunky =
2346 Curl_compareheader(ptr,
2347 STRCONST("Transfer-Encoding:"), STRCONST("chunked"));
2350 if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
2351 (((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) &&
2352 http->postsize < 0) ||
2353 ((data->set.upload || httpreq == HTTPREQ_POST) &&
2354 data->state.infilesize == -1))) {
2355 if(conn->bits.authneg)
2356 /* don't enable chunked during auth neg */
2358 else if(Curl_use_http_1_1plus(data, conn)) {
2359 if(conn->httpversion < 20)
2360 /* HTTP, upload, unknown file size and not HTTP 1.0 */
2361 data->req.upload_chunky = TRUE;
2364 failf(data, "Chunky upload is not supported by HTTP 1.0");
2365 return CURLE_UPLOAD_FAILED;
2369 /* else, no chunky upload */
2370 data->req.upload_chunky = FALSE;
2373 if(data->req.upload_chunky)
2374 *tep = "Transfer-Encoding: chunked\r\n";
2379 CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
2380 struct dynbuf *r, Curl_HttpReq httpreq)
2383 /* Hyper always handles the body separately */
2384 curl_off_t included_body = 0;
2386 /* from this point down, this function should not be used */
2387 #define Curl_buffer_send(a,b,c,d,e) CURLE_OK
2389 CURLcode result = CURLE_OK;
2390 struct HTTP *http = data->req.p.http;
2393 /* If 'authdone' is FALSE, we must not set the write socket index to the
2394 Curl_transfer() call below, as we're not ready to actually upload any
2399 case HTTPREQ_PUT: /* Let's PUT the data to the server! */
2401 if(conn->bits.authneg)
2404 http->postsize = data->state.infilesize;
2406 if((http->postsize != -1) && !data->req.upload_chunky &&
2407 (conn->bits.authneg ||
2408 !Curl_checkheaders(data, STRCONST("Content-Length")))) {
2409 /* only add Content-Length if not uploading chunked */
2410 result = Curl_dyn_addf(r, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
2411 "\r\n", http->postsize);
2416 if(http->postsize) {
2417 result = expect100(data, conn, r);
2422 /* end of headers */
2423 result = Curl_dyn_addn(r, STRCONST("\r\n"));
2427 /* set the upload size to the progress meter */
2428 Curl_pgrsSetUploadSize(data, http->postsize);
2430 /* this sends the buffer and frees all the buffer resources */
2431 result = Curl_buffer_send(r, data, &data->info.request_size, 0,
2434 failf(data, "Failed sending PUT request");
2436 /* prepare for transfer */
2437 Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
2438 http->postsize?FIRSTSOCKET:-1);
2443 case HTTPREQ_POST_FORM:
2444 case HTTPREQ_POST_MIME:
2445 /* This is form posting using mime data. */
2446 if(conn->bits.authneg) {
2447 /* nothing to post! */
2448 result = Curl_dyn_addn(r, STRCONST("Content-Length: 0\r\n\r\n"));
2452 result = Curl_buffer_send(r, data, &data->info.request_size, 0,
2455 failf(data, "Failed sending POST request");
2457 /* setup variables for the upcoming transfer */
2458 Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
2462 data->state.infilesize = http->postsize;
2464 /* We only set Content-Length and allow a custom Content-Length if
2465 we don't upload data chunked, as RFC2616 forbids us to set both
2466 kinds of headers (Transfer-Encoding: chunked and Content-Length) */
2467 if(http->postsize != -1 && !data->req.upload_chunky &&
2468 (conn->bits.authneg ||
2469 !Curl_checkheaders(data, STRCONST("Content-Length")))) {
2470 /* we allow replacing this header if not during auth negotiation,
2471 although it isn't very wise to actually set your own */
2472 result = Curl_dyn_addf(r,
2473 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
2474 "\r\n", http->postsize);
2479 #ifndef CURL_DISABLE_MIME
2480 /* Output mime-generated headers. */
2482 struct curl_slist *hdr;
2484 for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) {
2485 result = Curl_dyn_addf(r, "%s\r\n", hdr->data);
2492 /* For really small posts we don't use Expect: headers at all, and for
2493 the somewhat bigger ones we allow the app to disable it. Just make
2494 sure that the expect100header is always set to the preferred value
2496 ptr = Curl_checkheaders(data, STRCONST("Expect"));
2498 data->state.expect100header =
2499 Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
2501 else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
2502 result = expect100(data, conn, r);
2507 data->state.expect100header = FALSE;
2509 /* make the request end in a true CRLF */
2510 result = Curl_dyn_addn(r, STRCONST("\r\n"));
2514 /* set the upload size to the progress meter */
2515 Curl_pgrsSetUploadSize(data, http->postsize);
2517 /* Read from mime structure. */
2518 data->state.fread_func = (curl_read_callback) Curl_mime_read;
2519 data->state.in = (void *) http->sendit;
2520 http->sending = HTTPSEND_BODY;
2522 /* this sends the buffer and frees all the buffer resources */
2523 result = Curl_buffer_send(r, data, &data->info.request_size, 0,
2526 failf(data, "Failed sending POST request");
2528 /* prepare for transfer */
2529 Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
2530 http->postsize?FIRSTSOCKET:-1);
2537 /* this is the simple POST, using x-www-form-urlencoded style */
2539 if(conn->bits.authneg)
2542 /* the size of the post body */
2543 http->postsize = data->state.infilesize;
2545 /* We only set Content-Length and allow a custom Content-Length if
2546 we don't upload data chunked, as RFC2616 forbids us to set both
2547 kinds of headers (Transfer-Encoding: chunked and Content-Length) */
2548 if((http->postsize != -1) && !data->req.upload_chunky &&
2549 (conn->bits.authneg ||
2550 !Curl_checkheaders(data, STRCONST("Content-Length")))) {
2551 /* we allow replacing this header if not during auth negotiation,
2552 although it isn't very wise to actually set your own */
2553 result = Curl_dyn_addf(r, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
2554 "\r\n", http->postsize);
2559 if(!Curl_checkheaders(data, STRCONST("Content-Type"))) {
2560 result = Curl_dyn_addn(r, STRCONST("Content-Type: application/"
2561 "x-www-form-urlencoded\r\n"));
2566 /* For really small posts we don't use Expect: headers at all, and for
2567 the somewhat bigger ones we allow the app to disable it. Just make
2568 sure that the expect100header is always set to the preferred value
2570 ptr = Curl_checkheaders(data, STRCONST("Expect"));
2572 data->state.expect100header =
2573 Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
2575 else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
2576 result = expect100(data, conn, r);
2581 data->state.expect100header = FALSE;
2584 /* With Hyper the body is always passed on separately */
2585 if(data->set.postfields) {
2587 /* In HTTP2, we send request body in DATA frame regardless of
2589 if(conn->httpversion != 20 &&
2590 !data->state.expect100header &&
2591 (http->postsize < MAX_INITIAL_POST_SIZE)) {
2592 /* if we don't use expect: 100 AND
2593 postsize is less than MAX_INITIAL_POST_SIZE
2595 then append the post data to the HTTP request header. This limit
2596 is no magic limit but only set to prevent really huge POSTs to
2597 get the data duplicated with malloc() and family. */
2599 /* end of headers! */
2600 result = Curl_dyn_addn(r, STRCONST("\r\n"));
2604 if(!data->req.upload_chunky) {
2605 /* We're not sending it 'chunked', append it to the request
2606 already now to reduce the number if send() calls */
2607 result = Curl_dyn_addn(r, data->set.postfields,
2608 (size_t)http->postsize);
2609 included_body = http->postsize;
2612 if(http->postsize) {
2614 /* Append the POST data chunky-style */
2615 msnprintf(chunk, sizeof(chunk), "%x\r\n", (int)http->postsize);
2616 result = Curl_dyn_add(r, chunk);
2618 included_body = http->postsize + strlen(chunk);
2619 result = Curl_dyn_addn(r, data->set.postfields,
2620 (size_t)http->postsize);
2622 result = Curl_dyn_addn(r, STRCONST("\r\n"));
2627 result = Curl_dyn_addn(r, STRCONST("\x30\x0d\x0a\x0d\x0a"));
2634 /* Make sure the progress information is accurate */
2635 Curl_pgrsSetUploadSize(data, http->postsize);
2638 /* A huge POST coming up, do data separate from the request */
2639 http->postdata = data->set.postfields;
2641 http->sending = HTTPSEND_BODY;
2643 data->state.fread_func = (curl_read_callback)readmoredata;
2644 data->state.in = (void *)data;
2646 /* set the upload size to the progress meter */
2647 Curl_pgrsSetUploadSize(data, http->postsize);
2649 /* end of headers! */
2650 result = Curl_dyn_addn(r, STRCONST("\r\n"));
2658 /* end of headers! */
2659 result = Curl_dyn_addn(r, STRCONST("\r\n"));
2663 if(data->req.upload_chunky && conn->bits.authneg) {
2664 /* Chunky upload is selected and we're negotiating auth still, send
2666 result = Curl_dyn_addn(r, (char *)STRCONST("\x30\x0d\x0a\x0d\x0a"));
2672 else if(data->state.infilesize) {
2673 /* set the upload size to the progress meter */
2674 Curl_pgrsSetUploadSize(data, http->postsize?http->postsize:-1);
2676 /* set the pointer to mark that we will send the post body using the
2677 read callback, but only if we're not in authenticate negotiation */
2678 if(!conn->bits.authneg)
2679 http->postdata = (char *)&http->postdata;
2682 /* issue the request */
2683 result = Curl_buffer_send(r, data, &data->info.request_size, included_body,
2687 failf(data, "Failed sending HTTP POST request");
2689 Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
2690 http->postdata?FIRSTSOCKET:-1);
2694 result = Curl_dyn_addn(r, STRCONST("\r\n"));
2698 /* issue the request */
2699 result = Curl_buffer_send(r, data, &data->info.request_size, 0,
2702 failf(data, "Failed sending HTTP request");
2704 /* HTTP GET/HEAD download: */
2705 Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
2711 #if !defined(CURL_DISABLE_COOKIES)
2712 CURLcode Curl_http_cookies(struct Curl_easy *data,
2713 struct connectdata *conn,
2716 CURLcode result = CURLE_OK;
2717 char *addcookies = NULL;
2718 if(data->set.str[STRING_COOKIE] &&
2719 !Curl_checkheaders(data, STRCONST("Cookie")))
2720 addcookies = data->set.str[STRING_COOKIE];
2722 if(data->cookies || addcookies) {
2723 struct Cookie *co = NULL; /* no cookies from start */
2726 if(data->cookies && data->state.cookie_engine) {
2727 const char *host = data->state.aptr.cookiehost ?
2728 data->state.aptr.cookiehost : conn->host.name;
2729 const bool secure_context =
2730 conn->handler->protocol&CURLPROTO_HTTPS ||
2731 strcasecompare("localhost", host) ||
2732 !strcmp(host, "127.0.0.1") ||
2733 !strcmp(host, "[::1]") ? TRUE : FALSE;
2734 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
2735 co = Curl_cookie_getlist(data->cookies, host, data->state.up.path,
2737 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
2740 struct Cookie *store = co;
2741 /* now loop through all cookies that matched */
2745 result = Curl_dyn_addn(r, STRCONST("Cookie: "));
2749 result = Curl_dyn_addf(r, "%s%s=%s", count?"; ":"",
2750 co->name, co->value);
2755 co = co->next; /* next cookie please */
2757 Curl_cookie_freelist(store);
2759 if(addcookies && !result) {
2761 result = Curl_dyn_addn(r, STRCONST("Cookie: "));
2763 result = Curl_dyn_addf(r, "%s%s", count?"; ":"", addcookies);
2767 if(count && !result)
2768 result = Curl_dyn_addn(r, STRCONST("\r\n"));
2777 CURLcode Curl_http_range(struct Curl_easy *data,
2778 Curl_HttpReq httpreq)
2780 if(data->state.use_range) {
2782 * A range is selected. We use different headers whether we're downloading
2783 * or uploading and we always let customized headers override our internal
2784 * ones if any such are specified.
2786 if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
2787 !Curl_checkheaders(data, STRCONST("Range"))) {
2788 /* if a line like this was already allocated, free the previous one */
2789 free(data->state.aptr.rangeline);
2790 data->state.aptr.rangeline = aprintf("Range: bytes=%s\r\n",
2793 else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
2794 !Curl_checkheaders(data, STRCONST("Content-Range"))) {
2796 /* if a line like this was already allocated, free the previous one */
2797 free(data->state.aptr.rangeline);
2799 if(data->set.set_resume_from < 0) {
2800 /* Upload resume was asked for, but we don't know the size of the
2801 remote part so we tell the server (and act accordingly) that we
2802 upload the whole file (again) */
2803 data->state.aptr.rangeline =
2804 aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T
2805 "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
2806 data->state.infilesize - 1, data->state.infilesize);
2809 else if(data->state.resume_from) {
2810 /* This is because "resume" was selected */
2811 curl_off_t total_expected_size =
2812 data->state.resume_from + data->state.infilesize;
2813 data->state.aptr.rangeline =
2814 aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T
2815 "/%" CURL_FORMAT_CURL_OFF_T "\r\n",
2816 data->state.range, total_expected_size-1,
2817 total_expected_size);
2820 /* Range was selected and then we just pass the incoming range and
2821 append total size */
2822 data->state.aptr.rangeline =
2823 aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n",
2824 data->state.range, data->state.infilesize);
2826 if(!data->state.aptr.rangeline)
2827 return CURLE_OUT_OF_MEMORY;
2833 CURLcode Curl_http_resume(struct Curl_easy *data,
2834 struct connectdata *conn,
2835 Curl_HttpReq httpreq)
2837 if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
2838 data->state.resume_from) {
2839 /**********************************************************************
2840 * Resuming upload in HTTP means that we PUT or POST and that we have
2841 * got a resume_from value set. The resume value has already created
2842 * a Range: header that will be passed along. We need to "fast forward"
2843 * the file the given number of bytes and decrease the assume upload
2844 * file size before we continue this venture in the dark lands of HTTP.
2845 * Resuming mime/form posting at an offset > 0 has no sense and is ignored.
2846 *********************************************************************/
2848 if(data->state.resume_from < 0) {
2850 * This is meant to get the size of the present remote-file by itself.
2851 * We don't support this now. Bail out!
2853 data->state.resume_from = 0;
2856 if(data->state.resume_from && !data->state.this_is_a_follow) {
2857 /* do we still game? */
2859 /* Now, let's read off the proper amount of bytes from the
2861 int seekerr = CURL_SEEKFUNC_CANTSEEK;
2862 if(conn->seek_func) {
2863 Curl_set_in_callback(data, true);
2864 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
2866 Curl_set_in_callback(data, false);
2869 if(seekerr != CURL_SEEKFUNC_OK) {
2870 curl_off_t passed = 0;
2872 if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
2873 failf(data, "Could not seek stream");
2874 return CURLE_READ_ERROR;
2876 /* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
2878 size_t readthisamountnow =
2879 (data->state.resume_from - passed > data->set.buffer_size) ?
2880 (size_t)data->set.buffer_size :
2881 curlx_sotouz(data->state.resume_from - passed);
2883 size_t actuallyread =
2884 data->state.fread_func(data->state.buffer, 1, readthisamountnow,
2887 passed += actuallyread;
2888 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
2889 /* this checks for greater-than only to make sure that the
2890 CURL_READFUNC_ABORT return code still aborts */
2891 failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T
2892 " bytes from the input", passed);
2893 return CURLE_READ_ERROR;
2895 } while(passed < data->state.resume_from);
2898 /* now, decrease the size of the read */
2899 if(data->state.infilesize>0) {
2900 data->state.infilesize -= data->state.resume_from;
2902 if(data->state.infilesize <= 0) {
2903 failf(data, "File already completely uploaded");
2904 return CURLE_PARTIAL_FILE;
2907 /* we've passed, proceed as normal */
2913 CURLcode Curl_http_firstwrite(struct Curl_easy *data,
2914 struct connectdata *conn,
2917 struct SingleRequest *k = &data->req;
2919 if(data->req.newurl) {
2920 if(conn->bits.close) {
2921 /* Abort after the headers if "follow Location" is set
2922 and we're set to close anyway. */
2923 k->keepon &= ~KEEP_RECV;
2927 /* We have a new url to load, but since we want to be able to re-use this
2928 connection properly, we read the full response in "ignore more" */
2929 k->ignorebody = TRUE;
2930 infof(data, "Ignoring the response-body");
2932 if(data->state.resume_from && !k->content_range &&
2933 (data->state.httpreq == HTTPREQ_GET) &&
2936 if(k->size == data->state.resume_from) {
2937 /* The resume point is at the end of file, consider this fine even if it
2938 doesn't allow resume from here. */
2939 infof(data, "The entire document is already downloaded");
2940 streamclose(conn, "already downloaded");
2941 /* Abort download */
2942 k->keepon &= ~KEEP_RECV;
2947 /* we wanted to resume a download, although the server doesn't seem to
2948 * support this and we did this with a GET (if it wasn't a GET we did a
2949 * POST or PUT resume) */
2950 failf(data, "HTTP server doesn't seem to support "
2951 "byte ranges. Cannot resume.");
2952 return CURLE_RANGE_ERROR;
2955 if(data->set.timecondition && !data->state.range) {
2956 /* A time condition has been set AND no ranges have been requested. This
2957 seems to be what chapter 13.3.4 of RFC 2616 defines to be the correct
2958 action for a HTTP/1.1 client */
2960 if(!Curl_meets_timecondition(data, k->timeofdoc)) {
2962 /* We're simulating a http 304 from server so we return
2963 what should have been returned from the server */
2964 data->info.httpcode = 304;
2965 infof(data, "Simulate a HTTP 304 response");
2966 /* we abort the transfer before it is completed == we ruin the
2967 re-use ability. Close the connection */
2968 streamclose(conn, "Simulated 304 handling");
2971 } /* we have a time condition */
2977 CURLcode Curl_transferencode(struct Curl_easy *data)
2979 if(!Curl_checkheaders(data, STRCONST("TE")) &&
2980 data->set.http_transfer_encoding) {
2981 /* When we are to insert a TE: header in the request, we must also insert
2982 TE in a Connection: header, so we need to merge the custom provided
2983 Connection: header and prevent the original to get sent. Note that if
2984 the user has inserted his/her own TE: header we don't do this magic
2985 but then assume that the user will handle it all! */
2986 char *cptr = Curl_checkheaders(data, STRCONST("Connection"));
2987 #define TE_HEADER "TE: gzip\r\n"
2989 Curl_safefree(data->state.aptr.te);
2992 cptr = Curl_copy_header_value(cptr);
2994 return CURLE_OUT_OF_MEMORY;
2997 /* Create the (updated) Connection: header */
2998 data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
2999 cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
3002 if(!data->state.aptr.te)
3003 return CURLE_OUT_OF_MEMORY;
3011 * Curl_http() gets called from the generic multi_do() function when a HTTP
3012 * request is to be performed. This creates and sends a properly constructed
3015 CURLcode Curl_http(struct Curl_easy *data, bool *done)
3017 struct connectdata *conn = data->conn;
3018 CURLcode result = CURLE_OK;
3020 Curl_HttpReq httpreq;
3021 const char *te = ""; /* transfer-encoding */
3022 const char *request;
3023 const char *httpstring;
3025 char *altused = NULL;
3026 const char *p_accept; /* Accept: string */
3028 /* Always consider the DO phase done after this function call, even if there
3029 may be parts of the request that are not yet sent, since we can deal with
3030 the rest of the request in the PERFORM phase. */
3033 if(conn->transport != TRNSPRT_QUIC) {
3034 if(conn->httpversion < 20) { /* unless the connection is re-used and
3036 switch(conn->negnpn) {
3037 case CURL_HTTP_VERSION_2:
3038 conn->httpversion = 20; /* we know we're on HTTP/2 now */
3040 result = Curl_http2_switched(data, NULL, 0);
3044 case CURL_HTTP_VERSION_1_1:
3045 /* continue with HTTP/1.1 when explicitly requested */
3048 /* Check if user wants to use HTTP/2 with clear TCP*/
3050 if(data->state.httpwant == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
3051 #ifndef CURL_DISABLE_PROXY
3052 if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
3053 /* We don't support HTTP/2 proxies yet. Also it's debatable
3054 whether or not this setting should apply to HTTP/2 proxies. */
3055 infof(data, "Ignoring HTTP/2 prior knowledge due to proxy");
3059 DEBUGF(infof(data, "HTTP/2 over clean TCP"));
3060 conn->httpversion = 20;
3062 result = Curl_http2_switched(data, NULL, 0);
3071 /* prepare for a http2 request */
3072 result = Curl_http2_setup(data, conn);
3077 http = data->req.p.http;
3080 result = Curl_http_host(data, conn);
3084 result = Curl_http_useragent(data);
3088 Curl_http_method(data, conn, &request, &httpreq);
3090 /* setup the authentication headers */
3093 if(data->state.up.query) {
3094 pq = aprintf("%s?%s", data->state.up.path, data->state.up.query);
3096 return CURLE_OUT_OF_MEMORY;
3098 result = Curl_http_output_auth(data, conn, request, httpreq,
3099 (pq ? pq : data->state.up.path), FALSE);
3105 Curl_safefree(data->state.aptr.ref);
3106 if(data->state.referer && !Curl_checkheaders(data, STRCONST("Referer"))) {
3107 data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer);
3108 if(!data->state.aptr.ref)
3109 return CURLE_OUT_OF_MEMORY;
3112 if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) &&
3113 data->set.str[STRING_ENCODING]) {
3114 Curl_safefree(data->state.aptr.accept_encoding);
3115 data->state.aptr.accept_encoding =
3116 aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
3117 if(!data->state.aptr.accept_encoding)
3118 return CURLE_OUT_OF_MEMORY;
3121 Curl_safefree(data->state.aptr.accept_encoding);
3124 /* we only consider transfer-encoding magic if libz support is built-in */
3125 result = Curl_transferencode(data);
3130 result = Curl_http_body(data, conn, httpreq, &te);
3134 p_accept = Curl_checkheaders(data,
3135 STRCONST("Accept"))?NULL:"Accept: */*\r\n";
3137 result = Curl_http_resume(data, conn, httpreq);
3141 result = Curl_http_range(data, httpreq);
3145 httpstring = get_http_string(data, conn);
3147 /* initialize a dynamic send-buffer */
3148 Curl_dyn_init(&req, DYN_HTTP_REQUEST);
3150 /* make sure the header buffer is reset - if there are leftovers from a
3151 previous transfer */
3152 Curl_dyn_reset(&data->state.headerb);
3154 /* add the main request stuff */
3155 /* GET/HEAD/POST/PUT */
3156 result = Curl_dyn_addf(&req, "%s ", request);
3158 result = Curl_http_target(data, conn, &req);
3160 Curl_dyn_free(&req);
3164 #ifndef CURL_DISABLE_ALTSVC
3165 if(conn->bits.altused && !Curl_checkheaders(data, STRCONST("Alt-Used"))) {
3166 altused = aprintf("Alt-Used: %s:%d\r\n",
3167 conn->conn_to_host.name, conn->conn_to_port);
3169 Curl_dyn_free(&req);
3170 return CURLE_OUT_OF_MEMORY;
3176 " HTTP/%s\r\n" /* HTTP version */
3178 "%s" /* proxyuserpwd */
3181 "%s" /* user agent */
3184 "%s" /* accept-encoding */
3186 "%s" /* Proxy-Connection */
3187 "%s" /* transfer-encoding */
3191 (data->state.aptr.host?data->state.aptr.host:""),
3192 data->state.aptr.proxyuserpwd?
3193 data->state.aptr.proxyuserpwd:"",
3194 data->state.aptr.userpwd?data->state.aptr.userpwd:"",
3195 (data->state.use_range && data->state.aptr.rangeline)?
3196 data->state.aptr.rangeline:"",
3197 (data->set.str[STRING_USERAGENT] &&
3198 *data->set.str[STRING_USERAGENT] &&
3199 data->state.aptr.uagent)?
3200 data->state.aptr.uagent:"",
3201 p_accept?p_accept:"",
3202 data->state.aptr.te?data->state.aptr.te:"",
3203 (data->set.str[STRING_ENCODING] &&
3204 *data->set.str[STRING_ENCODING] &&
3205 data->state.aptr.accept_encoding)?
3206 data->state.aptr.accept_encoding:"",
3207 (data->state.referer && data->state.aptr.ref)?
3208 data->state.aptr.ref:"" /* Referer: <data> */,
3209 #ifndef CURL_DISABLE_PROXY
3210 (conn->bits.httpproxy &&
3211 !conn->bits.tunnel_proxy &&
3212 !Curl_checkheaders(data, STRCONST("Proxy-Connection")) &&
3213 !Curl_checkProxyheaders(data,
3215 STRCONST("Proxy-Connection")))?
3216 "Proxy-Connection: Keep-Alive\r\n":"",
3221 altused ? altused : ""
3224 /* clear userpwd and proxyuserpwd to avoid re-using old credentials
3225 * from re-used connections */
3226 Curl_safefree(data->state.aptr.userpwd);
3227 Curl_safefree(data->state.aptr.proxyuserpwd);
3231 Curl_dyn_free(&req);
3235 if(!(conn->handler->flags&PROTOPT_SSL) &&
3236 conn->httpversion != 20 &&
3237 (data->state.httpwant == CURL_HTTP_VERSION_2)) {
3238 /* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
3240 result = Curl_http2_request_upgrade(&req, data);
3242 Curl_dyn_free(&req);
3247 result = Curl_http_cookies(data, conn, &req);
3249 result = Curl_add_timecondition(data, &req);
3251 result = Curl_add_custom_headers(data, FALSE, &req);
3254 http->postdata = NULL; /* nothing to post at this point */
3255 if((httpreq == HTTPREQ_GET) ||
3256 (httpreq == HTTPREQ_HEAD))
3257 Curl_pgrsSetUploadSize(data, 0); /* nothing */
3259 /* bodysend takes ownership of the 'req' memory on success */
3260 result = Curl_http_bodysend(data, conn, &req, httpreq);
3263 Curl_dyn_free(&req);
3267 if((http->postsize > -1) &&
3268 (http->postsize <= data->req.writebytecount) &&
3269 (http->sending != HTTPSEND_REQUEST))
3270 data->req.upload_done = TRUE;
3272 if(data->req.writebytecount) {
3273 /* if a request-body has been sent off, we make sure this progress is noted
3275 Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
3276 if(Curl_pgrsUpdate(data))
3277 result = CURLE_ABORTED_BY_CALLBACK;
3279 if(!http->postsize) {
3280 /* already sent the entire request body, mark the "upload" as
3282 infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
3283 " out of %" CURL_FORMAT_CURL_OFF_T " bytes",
3284 data->req.writebytecount, http->postsize);
3285 data->req.upload_done = TRUE;
3286 data->req.keepon &= ~KEEP_SEND; /* we're done writing */
3287 data->req.exp100 = EXP100_SEND_DATA; /* already sent */
3288 Curl_expire_done(data, EXPIRE_100_TIMEOUT);
3292 if((conn->httpversion == 20) && data->req.upload_chunky)
3293 /* upload_chunky was set above to set up the request in a chunky fashion,
3294 but is disabled here again to avoid that the chunked encoded version is
3295 actually used when sending the request body over h2 */
3296 data->req.upload_chunky = FALSE;
3300 #endif /* USE_HYPER */
3303 STATUS_UNKNOWN, /* not enough data to tell yet */
3304 STATUS_DONE, /* a status line was read */
3305 STATUS_BAD /* not a status line */
3309 /* Check a string for a prefix. Check no more than 'len' bytes */
3310 static bool checkprefixmax(const char *prefix, const char *buffer, size_t len)
3312 size_t ch = CURLMIN(strlen(prefix), len);
3313 return curl_strnequal(prefix, buffer, ch);
3319 * Returns TRUE if member of the list matches prefix of string
3322 checkhttpprefix(struct Curl_easy *data,
3323 const char *s, size_t len)
3325 struct curl_slist *head = data->set.http200aliases;
3326 statusline rc = STATUS_BAD;
3327 statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN;
3330 if(checkprefixmax(head->data, s, len)) {
3337 if((rc != STATUS_DONE) && (checkprefixmax("HTTP/", s, len)))
3343 #ifndef CURL_DISABLE_RTSP
3345 checkrtspprefix(struct Curl_easy *data,
3346 const char *s, size_t len)
3348 statusline result = STATUS_BAD;
3349 statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN;
3350 (void)data; /* unused */
3351 if(checkprefixmax("RTSP/", s, len))
3356 #endif /* CURL_DISABLE_RTSP */
3359 checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
3360 const char *s, size_t len)
3362 #ifndef CURL_DISABLE_RTSP
3363 if(conn->handler->protocol & CURLPROTO_RTSP)
3364 return checkrtspprefix(data, s, len);
3367 #endif /* CURL_DISABLE_RTSP */
3369 return checkhttpprefix(data, s, len);
3373 * Curl_http_header() parses a single response header.
3375 CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
3379 struct SingleRequest *k = &data->req;
3380 /* Check for Content-Length: header lines to get size */
3381 if(!k->http_bodyless &&
3382 !data->set.ignorecl && checkprefix("Content-Length:", headp)) {
3383 curl_off_t contentlength;
3384 CURLofft offt = curlx_strtoofft(headp + strlen("Content-Length:"),
3385 NULL, 10, &contentlength);
3387 if(offt == CURL_OFFT_OK) {
3388 k->size = contentlength;
3389 k->maxdownload = k->size;
3391 else if(offt == CURL_OFFT_FLOW) {
3393 if(data->set.max_filesize) {
3394 failf(data, "Maximum file size exceeded");
3395 return CURLE_FILESIZE_EXCEEDED;
3397 streamclose(conn, "overflow content-length");
3398 infof(data, "Overflow Content-Length: value");
3401 /* negative or just rubbish - bad HTTP */
3402 failf(data, "Invalid Content-Length: value");
3403 return CURLE_WEIRD_SERVER_REPLY;
3406 /* check for Content-Type: header lines to get the MIME-type */
3407 else if(checkprefix("Content-Type:", headp)) {
3408 char *contenttype = Curl_copy_header_value(headp);
3410 return CURLE_OUT_OF_MEMORY;
3412 /* ignore empty data */
3415 Curl_safefree(data->info.contenttype);
3416 data->info.contenttype = contenttype;
3419 #ifndef CURL_DISABLE_PROXY
3420 else if((conn->httpversion == 10) &&
3421 conn->bits.httpproxy &&
3422 Curl_compareheader(headp,
3423 STRCONST("Proxy-Connection:"),
3424 STRCONST("keep-alive"))) {
3426 * When a HTTP/1.0 reply comes when using a proxy, the
3427 * 'Proxy-Connection: keep-alive' line tells us the
3428 * connection will be kept alive for our pleasure.
3429 * Default action for 1.0 is to close.
3431 connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */
3432 infof(data, "HTTP/1.0 proxy connection set to keep alive");
3434 else if((conn->httpversion == 11) &&
3435 conn->bits.httpproxy &&
3436 Curl_compareheader(headp,
3437 STRCONST("Proxy-Connection:"),
3438 STRCONST("close"))) {
3440 * We get a HTTP/1.1 response from a proxy and it says it'll
3441 * close down after this transfer.
3443 connclose(conn, "Proxy-Connection: asked to close after done");
3444 infof(data, "HTTP/1.1 proxy connection set close");
3447 else if((conn->httpversion == 10) &&
3448 Curl_compareheader(headp,
3449 STRCONST("Connection:"),
3450 STRCONST("keep-alive"))) {
3452 * A HTTP/1.0 reply with the 'Connection: keep-alive' line
3453 * tells us the connection will be kept alive for our
3454 * pleasure. Default action for 1.0 is to close.
3456 * [RFC2068, section 19.7.1] */
3457 connkeep(conn, "Connection keep-alive");
3458 infof(data, "HTTP/1.0 connection set to keep alive");
3460 else if(Curl_compareheader(headp,
3461 STRCONST("Connection:"), STRCONST("close"))) {
3463 * [RFC 2616, section 8.1.2.1]
3464 * "Connection: close" is HTTP/1.1 language and means that
3465 * the connection will close when this request has been
3468 streamclose(conn, "Connection: close used");
3470 else if(!k->http_bodyless && checkprefix("Transfer-Encoding:", headp)) {
3471 /* One or more encodings. We check for chunked and/or a compression
3474 * [RFC 2616, section 3.6.1] A 'chunked' transfer encoding
3475 * means that the server will send a series of "chunks". Each
3476 * chunk starts with line with info (including size of the
3477 * coming block) (terminated with CRLF), then a block of data
3478 * with the previously mentioned size. There can be any amount
3479 * of chunks, and a chunk-data set to zero signals the
3482 result = Curl_build_unencoding_stack(data,
3483 headp + strlen("Transfer-Encoding:"),
3488 /* if this isn't chunked, only close can signal the end of this transfer
3489 as Content-Length is said not to be trusted for transfer-encoding! */
3490 connclose(conn, "HTTP/1.1 transfer-encoding without chunks");
3491 k->ignore_cl = TRUE;
3494 else if(!k->http_bodyless && checkprefix("Content-Encoding:", headp) &&
3495 data->set.str[STRING_ENCODING]) {
3497 * Process Content-Encoding. Look for the values: identity,
3498 * gzip, deflate, compress, x-gzip and x-compress. x-gzip and
3499 * x-compress are the same as gzip and compress. (Sec 3.5 RFC
3500 * 2616). zlib cannot handle compress. However, errors are
3501 * handled further down when the response body is processed
3503 result = Curl_build_unencoding_stack(data,
3504 headp + strlen("Content-Encoding:"),
3509 else if(checkprefix("Retry-After:", headp)) {
3510 /* Retry-After = HTTP-date / delay-seconds */
3511 curl_off_t retry_after = 0; /* zero for unknown or "now" */
3512 time_t date = Curl_getdate_capped(headp + strlen("Retry-After:"));
3514 /* not a date, try it as a decimal number */
3515 (void)curlx_strtoofft(headp + strlen("Retry-After:"),
3516 NULL, 10, &retry_after);
3519 /* convert date to number of seconds into the future */
3520 retry_after = date - time(NULL);
3521 data->info.retry_after = retry_after; /* store it */
3523 else if(!k->http_bodyless && checkprefix("Content-Range:", headp)) {
3524 /* Content-Range: bytes [num]-
3525 Content-Range: bytes: [num]-
3526 Content-Range: [num]-
3527 Content-Range: [asterisk]/[total]
3529 The second format was added since Sun's webserver
3530 JavaWebServer/1.1.1 obviously sends the header this way!
3531 The third added since some servers use that!
3532 The forth means the requested range was unsatisfied.
3535 char *ptr = headp + strlen("Content-Range:");
3537 /* Move forward until first digit or asterisk */
3538 while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
3541 /* if it truly stopped on a digit */
3543 if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) {
3544 if(data->state.resume_from == k->offset)
3545 /* we asked for a resume and we got it */
3546 k->content_range = TRUE;
3550 data->state.resume_from = 0; /* get everything */
3552 #if !defined(CURL_DISABLE_COOKIES)
3553 else if(data->cookies && data->state.cookie_engine &&
3554 checkprefix("Set-Cookie:", headp)) {
3555 /* If there is a custom-set Host: name, use it here, or else use real peer
3557 const char *host = data->state.aptr.cookiehost?
3558 data->state.aptr.cookiehost:conn->host.name;
3559 const bool secure_context =
3560 conn->handler->protocol&CURLPROTO_HTTPS ||
3561 strcasecompare("localhost", host) ||
3562 !strcmp(host, "127.0.0.1") ||
3563 !strcmp(host, "[::1]") ? TRUE : FALSE;
3565 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
3566 CURL_LOCK_ACCESS_SINGLE);
3567 Curl_cookie_add(data, data->cookies, TRUE, FALSE,
3568 headp + strlen("Set-Cookie:"), host,
3569 data->state.up.path, secure_context);
3570 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
3573 else if(!k->http_bodyless && checkprefix("Last-Modified:", headp) &&
3574 (data->set.timecondition || data->set.get_filetime) ) {
3575 k->timeofdoc = Curl_getdate_capped(headp + strlen("Last-Modified:"));
3576 if(data->set.get_filetime)
3577 data->info.filetime = k->timeofdoc;
3579 else if((checkprefix("WWW-Authenticate:", headp) &&
3580 (401 == k->httpcode)) ||
3581 (checkprefix("Proxy-authenticate:", headp) &&
3582 (407 == k->httpcode))) {
3584 bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
3585 char *auth = Curl_copy_header_value(headp);
3587 return CURLE_OUT_OF_MEMORY;
3589 result = Curl_http_input_auth(data, proxy, auth);
3597 else if(checkprefix("Persistent-Auth:", headp)) {
3598 struct negotiatedata *negdata = &conn->negotiate;
3599 struct auth *authp = &data->state.authhost;
3600 if(authp->picked == CURLAUTH_NEGOTIATE) {
3601 char *persistentauth = Curl_copy_header_value(headp);
3603 return CURLE_OUT_OF_MEMORY;
3604 negdata->noauthpersist = checkprefix("false", persistentauth)?
3606 negdata->havenoauthpersist = TRUE;
3607 infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
3608 negdata->noauthpersist, persistentauth);
3609 free(persistentauth);
3613 else if((k->httpcode >= 300 && k->httpcode < 400) &&
3614 checkprefix("Location:", headp) &&
3615 !data->req.location) {
3616 /* this is the URL that the server advises us to use instead */
3617 char *location = Curl_copy_header_value(headp);
3619 return CURLE_OUT_OF_MEMORY;
3621 /* ignore empty data */
3624 data->req.location = location;
3626 if(data->set.http_follow_location) {
3627 DEBUGASSERT(!data->req.newurl);
3628 data->req.newurl = strdup(data->req.location); /* clone */
3629 if(!data->req.newurl)
3630 return CURLE_OUT_OF_MEMORY;
3632 /* some cases of POST and PUT etc needs to rewind the data
3633 stream at this point */
3634 result = http_perhapsrewind(data, conn);
3641 #ifndef CURL_DISABLE_HSTS
3642 /* If enabled, the header is incoming and this is over HTTPS */
3643 else if(data->hsts && checkprefix("Strict-Transport-Security:", headp) &&
3644 (conn->handler->flags & PROTOPT_SSL)) {
3646 Curl_hsts_parse(data->hsts, data->state.up.hostname,
3647 headp + strlen("Strict-Transport-Security:"));
3649 infof(data, "Illegal STS header skipped");
3652 infof(data, "Parsed STS header fine (%zu entries)",
3653 data->hsts->list.size);
3657 #ifndef CURL_DISABLE_ALTSVC
3658 /* If enabled, the header is incoming and this is over HTTPS */
3659 else if(data->asi && checkprefix("Alt-Svc:", headp) &&
3660 ((conn->handler->flags & PROTOPT_SSL) ||
3662 /* allow debug builds to circumvent the HTTPS restriction */
3663 getenv("CURL_ALTSVC_HTTP")
3668 /* the ALPN of the current request */
3669 enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
3670 result = Curl_altsvc_parse(data, data->asi,
3671 headp + strlen("Alt-Svc:"),
3672 id, conn->host.name,
3673 curlx_uitous(conn->remote_port));
3678 else if(conn->handler->protocol & CURLPROTO_RTSP) {
3679 result = Curl_rtsp_parseheader(data, headp);
3687 * Called after the first HTTP response line (the status line) has been
3688 * received and parsed.
3691 CURLcode Curl_http_statusline(struct Curl_easy *data,
3692 struct connectdata *conn)
3694 struct SingleRequest *k = &data->req;
3695 data->info.httpcode = k->httpcode;
3697 data->info.httpversion = conn->httpversion;
3698 if(!data->state.httpversion ||
3699 data->state.httpversion > conn->httpversion)
3700 /* store the lowest server version we encounter */
3701 data->state.httpversion = conn->httpversion;
3704 * This code executes as part of processing the header. As a
3705 * result, it's not totally clear how to interpret the
3706 * response code yet as that depends on what other headers may
3707 * be present. 401 and 407 may be errors, but may be OK
3708 * depending on how authentication is working. Other codes
3709 * are definitely errors, so give up here.
3711 if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
3712 k->httpcode == 416) {
3713 /* "Requested Range Not Satisfiable", just proceed and
3714 pretend this is no error */
3715 k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
3718 if(conn->httpversion == 10) {
3719 /* Default action for HTTP/1.0 must be to close, unless
3720 we get one of those fancy headers that tell us the
3721 server keeps it open for us! */
3722 infof(data, "HTTP 1.0, assume close after body");
3723 connclose(conn, "HTTP/1.0 close after body");
3725 else if(conn->httpversion == 20 ||
3726 (k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) {
3727 DEBUGF(infof(data, "HTTP/2 found, allow multiplexing"));
3728 /* HTTP/2 cannot avoid multiplexing since it is a core functionality
3730 conn->bundle->multiuse = BUNDLE_MULTIPLEX;
3732 else if(conn->httpversion >= 11 &&
3733 !conn->bits.close) {
3734 /* If HTTP version is >= 1.1 and connection is persistent */
3736 "HTTP 1.1 or later with persistent connection"));
3739 k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200;
3740 switch(k->httpcode) {
3742 /* (quote from RFC2616, section 10.3.5): The 304 response
3743 * MUST NOT contain a message-body, and thus is always
3744 * terminated by the first empty line after the header
3746 if(data->set.timecondition)
3747 data->info.timecond = TRUE;
3750 /* (quote from RFC2616, section 10.2.5): The server has
3751 * fulfilled the request but does not need to return an
3752 * entity-body ... The 204 response MUST NOT include a
3753 * message-body, and thus is always terminated by the first
3754 * empty line after the header fields. */
3757 k->http_bodyless = TRUE;
3765 /* Content-Length must be ignored if any Transfer-Encoding is present in the
3766 response. Refer to RFC 7230 section 3.3.3 and RFC2616 section 4.4. This is
3767 figured out here after all headers have been received but before the final
3768 call to the user's header callback, so that a valid content length can be
3769 retrieved by the user in the final call. */
3770 CURLcode Curl_http_size(struct Curl_easy *data)
3772 struct SingleRequest *k = &data->req;
3773 if(data->req.ignore_cl || k->chunk) {
3774 k->size = k->maxdownload = -1;
3776 else if(k->size != -1) {
3777 if(data->set.max_filesize &&
3778 k->size > data->set.max_filesize) {
3779 failf(data, "Maximum file size exceeded");
3780 return CURLE_FILESIZE_EXCEEDED;
3782 Curl_pgrsSetDownloadSize(data, k->size);
3783 k->maxdownload = k->size;
3788 static CURLcode verify_header(struct Curl_easy *data)
3790 struct SingleRequest *k = &data->req;
3791 const char *header = Curl_dyn_ptr(&data->state.headerb);
3792 size_t hlen = Curl_dyn_len(&data->state.headerb);
3793 char *ptr = memchr(header, 0x00, hlen);
3795 /* this is bad, bail out */
3796 failf(data, "Nul byte in header");
3797 return CURLE_WEIRD_SERVER_REPLY;
3799 if(k->headerline < 2)
3800 /* the first "header" is the status-line and it has no colon */
3802 ptr = memchr(header, ':', hlen);
3804 /* this is bad, bail out */
3805 failf(data, "Header without colon");
3806 return CURLE_WEIRD_SERVER_REPLY;
3812 * Read any HTTP header lines from the server and pass them to the client app.
3814 CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
3815 struct connectdata *conn,
3820 struct SingleRequest *k = &data->req;
3821 ssize_t onread = *nread;
3822 char *ostr = k->str;
3827 /* header line within buffer loop */
3833 /* str_start is start of line within buf */
3836 /* data is in network encoding so use 0x0a instead of '\n' */
3837 end_ptr = memchr(str_start, 0x0a, *nread);
3840 /* Not a complete header line within buffer, append the data to
3841 the end of the headerbuff. */
3842 result = Curl_dyn_addn(&data->state.headerb, str_start, *nread);
3846 if(!k->headerline) {
3847 /* check if this looks like a protocol header */
3849 checkprotoprefix(data, conn,
3850 Curl_dyn_ptr(&data->state.headerb),
3851 Curl_dyn_len(&data->state.headerb));
3853 if(st == STATUS_BAD) {
3854 /* this is not the beginning of a protocol first header line */
3856 k->badheader = HEADER_ALLBAD;
3857 streamclose(conn, "bad HTTP: No end-of-message indicator");
3858 if(!data->set.http09_allowed) {
3859 failf(data, "Received HTTP/0.9 when not allowed");
3860 return CURLE_UNSUPPORTED_PROTOCOL;
3866 break; /* read more and try again */
3869 /* decrease the size of the remaining (supposed) header line */
3870 rest_length = (end_ptr - k->str) + 1;
3871 *nread -= (ssize_t)rest_length;
3873 k->str = end_ptr + 1; /* move past new line */
3875 full_length = k->str - str_start;
3877 result = Curl_dyn_addn(&data->state.headerb, str_start, full_length);
3882 * We now have a FULL header line in 'headerb'.
3885 if(!k->headerline) {
3886 /* the first read header */
3887 statusline st = checkprotoprefix(data, conn,
3888 Curl_dyn_ptr(&data->state.headerb),
3889 Curl_dyn_len(&data->state.headerb));
3890 if(st == STATUS_BAD) {
3891 streamclose(conn, "bad HTTP: No end-of-message indicator");
3892 /* this is not the beginning of a protocol first header line */
3893 if(!data->set.http09_allowed) {
3894 failf(data, "Received HTTP/0.9 when not allowed");
3895 return CURLE_UNSUPPORTED_PROTOCOL;
3899 /* since there's more, this is a partial bad header */
3900 k->badheader = HEADER_PARTHEADER;
3902 /* this was all we read so it's all a bad header */
3903 k->badheader = HEADER_ALLBAD;
3912 /* headers are in network encoding so use 0x0a and 0x0d instead of '\n'
3914 headp = Curl_dyn_ptr(&data->state.headerb);
3915 if((0x0a == *headp) || (0x0d == *headp)) {
3917 /* Zero-length header line means end of headers! */
3920 headp++; /* pass the \r byte */
3922 headp++; /* pass the \n byte */
3924 if(100 <= k->httpcode && 199 >= k->httpcode) {
3925 /* "A user agent MAY ignore unexpected 1xx status responses." */
3926 switch(k->httpcode) {
3929 * We have made a HTTP PUT or POST and this is 1.1-lingo
3930 * that tells us that the server is OK with this and ready
3931 * to receive the data.
3932 * However, we'll get more headers now so we must get
3933 * back into the header-parsing state!
3936 k->headerline = 0; /* restart the header line counter */
3938 /* if we did wait for this do enable write now! */
3939 if(k->exp100 > EXP100_SEND_DATA) {
3940 k->exp100 = EXP100_SEND_DATA;
3941 k->keepon |= KEEP_SEND;
3942 Curl_expire_done(data, EXPIRE_100_TIMEOUT);
3946 /* Switching Protocols */
3947 if(k->upgr101 == UPGR101_REQUESTED) {
3948 /* Switching to HTTP/2 */
3949 infof(data, "Received 101");
3950 k->upgr101 = UPGR101_RECEIVED;
3952 /* we'll get more headers (HTTP/2 response) */
3954 k->headerline = 0; /* restart the header line counter */
3956 /* switch to http2 now. The bytes after response headers
3957 are also processed here, otherwise they are lost. */
3958 result = Curl_http2_switched(data, k->str, *nread);
3964 /* Switching to another protocol (e.g. WebSocket) */
3965 k->header = FALSE; /* no more header to parse! */
3969 /* the status code 1xx indicates a provisional response, so
3970 we'll get another set of headers */
3972 k->headerline = 0; /* restart the header line counter */
3977 k->header = FALSE; /* no more header to parse! */
3979 if((k->size == -1) && !k->chunk && !conn->bits.close &&
3980 (conn->httpversion == 11) &&
3981 !(conn->handler->protocol & CURLPROTO_RTSP) &&
3982 data->state.httpreq != HTTPREQ_HEAD) {
3983 /* On HTTP 1.1, when connection is not to get closed, but no
3984 Content-Length nor Transfer-Encoding chunked have been
3985 received, according to RFC2616 section 4.4 point 5, we
3986 assume that the server will close the connection to
3987 signal the end of the document. */
3988 infof(data, "no chunk, no close, no size. Assume close to "
3990 streamclose(conn, "HTTP: No end-of-message indicator");
3995 result = Curl_http_size(data);
4000 /* At this point we have some idea about the fate of the connection.
4001 If we are closing the connection it may result auth failure. */
4002 #if defined(USE_NTLM)
4003 if(conn->bits.close &&
4004 (((data->req.httpcode == 401) &&
4005 (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
4006 ((data->req.httpcode == 407) &&
4007 (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
4008 infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
4009 data->state.authproblem = TRUE;
4012 #if defined(USE_SPNEGO)
4013 if(conn->bits.close &&
4014 (((data->req.httpcode == 401) &&
4015 (conn->http_negotiate_state == GSS_AUTHRECV)) ||
4016 ((data->req.httpcode == 407) &&
4017 (conn->proxy_negotiate_state == GSS_AUTHRECV)))) {
4018 infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
4019 data->state.authproblem = TRUE;
4021 if((conn->http_negotiate_state == GSS_AUTHDONE) &&
4022 (data->req.httpcode != 401)) {
4023 conn->http_negotiate_state = GSS_AUTHSUCC;
4025 if((conn->proxy_negotiate_state == GSS_AUTHDONE) &&
4026 (data->req.httpcode != 407)) {
4027 conn->proxy_negotiate_state = GSS_AUTHSUCC;
4031 /* now, only output this if the header AND body are requested:
4033 writetype = CLIENTWRITE_HEADER |
4034 (data->set.include_header ? CLIENTWRITE_BODY : 0) |
4035 ((k->httpcode/100 == 1) ? CLIENTWRITE_1XX : 0);
4037 headerlen = Curl_dyn_len(&data->state.headerb);
4038 result = Curl_client_write(data, writetype,
4039 Curl_dyn_ptr(&data->state.headerb),
4044 data->info.header_size += (long)headerlen;
4045 data->req.headerbytecount += (long)headerlen;
4048 * When all the headers have been parsed, see if we should give
4049 * up and return an error.
4051 if(http_should_fail(data)) {
4052 failf(data, "The requested URL returned error: %d",
4054 return CURLE_HTTP_RETURNED_ERROR;
4057 data->req.deductheadercount =
4058 (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
4060 /* Curl_http_auth_act() checks what authentication methods
4061 * that are available and decides which one (if any) to
4062 * use. It will set 'newurl' if an auth method was picked. */
4063 result = Curl_http_auth_act(data);
4068 if(k->httpcode >= 300) {
4069 if((!conn->bits.authneg) && !conn->bits.close &&
4070 !conn->bits.rewindaftersend) {
4072 * General treatment of errors when about to send data. Including :
4073 * "417 Expectation Failed", while waiting for 100-continue.
4075 * The check for close above is done simply because of something
4076 * else has already deemed the connection to get closed then
4077 * something else should've considered the big picture and we
4080 * rewindaftersend indicates that something has told libcurl to
4081 * continue sending even if it gets discarded
4084 switch(data->state.httpreq) {
4087 case HTTPREQ_POST_FORM:
4088 case HTTPREQ_POST_MIME:
4089 /* We got an error response. If this happened before the whole
4090 * request body has been sent we stop sending and mark the
4091 * connection for closure after we've read the entire response.
4093 Curl_expire_done(data, EXPIRE_100_TIMEOUT);
4094 if(!k->upload_done) {
4095 if((k->httpcode == 417) && data->state.expect100header) {
4096 /* 417 Expectation Failed - try again without the Expect
4098 infof(data, "Got 417 while waiting for a 100");
4099 data->state.disableexpect = TRUE;
4100 DEBUGASSERT(!data->req.newurl);
4101 data->req.newurl = strdup(data->state.url);
4102 Curl_done_sending(data, k);
4104 else if(data->set.http_keep_sending_on_error) {
4105 infof(data, "HTTP error before end of send, keep sending");
4106 if(k->exp100 > EXP100_SEND_DATA) {
4107 k->exp100 = EXP100_SEND_DATA;
4108 k->keepon |= KEEP_SEND;
4112 infof(data, "HTTP error before end of send, stop sending");
4113 streamclose(conn, "Stop sending data before everything sent");
4114 result = Curl_done_sending(data, k);
4117 k->upload_done = TRUE;
4118 if(data->state.expect100header)
4119 k->exp100 = EXP100_FAILED;
4124 default: /* default label present to avoid compiler warnings */
4129 if(conn->bits.rewindaftersend) {
4130 /* We rewind after a complete send, so thus we continue
4132 infof(data, "Keep sending data to get tossed away");
4133 k->keepon |= KEEP_SEND;
4139 * really end-of-headers.
4141 * If we requested a "no body", this is a good time to get
4142 * out and return home.
4144 if(data->set.opt_no_body)
4145 *stop_reading = TRUE;
4146 #ifndef CURL_DISABLE_RTSP
4147 else if((conn->handler->protocol & CURLPROTO_RTSP) &&
4148 (data->set.rtspreq == RTSPREQ_DESCRIBE) &&
4150 /* Respect section 4.4 of rfc2326: If the Content-Length header is
4151 absent, a length 0 must be assumed. It will prevent libcurl from
4152 hanging on DESCRIBE request that got refused for whatever
4154 *stop_reading = TRUE;
4157 /* If max download size is *zero* (nothing) we already have
4158 nothing and can safely return ok now! But for HTTP/2, we'd
4159 like to call http2_handle_stream_close to properly close a
4160 stream. In order to do this, we keep reading until we
4161 close the stream. */
4162 if(0 == k->maxdownload
4163 #if defined(USE_NGHTTP2)
4164 && !((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
4165 conn->httpversion == 20)
4168 *stop_reading = TRUE;
4171 /* we make sure that this socket isn't read more now */
4172 k->keepon &= ~KEEP_RECV;
4175 Curl_debug(data, CURLINFO_HEADER_IN, str_start, headerlen);
4176 break; /* exit header line loop */
4179 /* We continue reading headers, reset the line-based header */
4180 Curl_dyn_reset(&data->state.headerb);
4185 * Checks for special headers coming up.
4188 writetype = CLIENTWRITE_HEADER;
4189 if(!k->headerline++) {
4190 /* This is the first header, it MUST be the error code line
4191 or else we consider this to be the body right away! */
4192 int httpversion_major;
4193 int rtspversion_major;
4195 #define HEADER1 headp /* no conversion needed, just use headp */
4197 if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
4199 * https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2
4201 * The response code is always a three-digit number in HTTP as the spec
4202 * says. We allow any three-digit number here, but we cannot make
4203 * guarantees on future behaviors since it isn't within the protocol.
4207 int httpversion = 0;
4209 nc = sscanf(HEADER1,
4210 " HTTP/%1d.%1d%c%3d%c",
4217 if(nc == 1 && httpversion_major >= 2 &&
4218 2 == sscanf(HEADER1, " HTTP/%1[23] %d", twoorthree, &k->httpcode)) {
4219 conn->httpversion = 0;
4224 /* There can only be a 4th response code digit stored in 'digit4' if
4225 all the other fields were parsed and stored first, so nc is 5 when
4228 The sscanf() line above will also allow zero-prefixed and negative
4229 numbers, so we check for that too here.
4231 else if(ISDIGIT(digit4) || (nc >= 4 && k->httpcode < 100)) {
4232 failf(data, "Unsupported response code in HTTP response");
4233 return CURLE_UNSUPPORTED_PROTOCOL;
4236 if((nc >= 4) && (' ' == separator)) {
4237 httpversion += 10 * httpversion_major;
4238 switch(httpversion) {
4247 conn->httpversion = (unsigned char)httpversion;
4250 failf(data, "Unsupported HTTP version (%u.%d) in response",
4251 httpversion/10, httpversion%10);
4252 return CURLE_UNSUPPORTED_PROTOCOL;
4255 if(k->upgr101 == UPGR101_RECEIVED) {
4256 /* supposedly upgraded to http2 now */
4257 if(conn->httpversion != 20)
4258 infof(data, "Lying server, not serving HTTP/2");
4260 if(conn->httpversion < 20) {
4261 conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
4262 infof(data, "Mark bundle as not supporting multiuse");
4266 /* this is the real world, not a Nirvana
4267 NCSA 1.5.x returns this crap when asked for HTTP/1.1
4269 nc = sscanf(HEADER1, " HTTP %3d", &k->httpcode);
4270 conn->httpversion = 10;
4272 /* If user has set option HTTP200ALIASES,
4273 compare header line against list of aliases
4277 checkhttpprefix(data,
4278 Curl_dyn_ptr(&data->state.headerb),
4279 Curl_dyn_len(&data->state.headerb));
4280 if(check == STATUS_DONE) {
4283 conn->httpversion = 10;
4288 failf(data, "Unsupported HTTP version in response");
4289 return CURLE_UNSUPPORTED_PROTOCOL;
4292 else if(conn->handler->protocol & CURLPROTO_RTSP) {
4295 nc = sscanf(HEADER1,
4296 " RTSP/%1d.%1d%c%3d",
4301 if((nc == 4) && (' ' == separator)) {
4302 conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
4310 result = Curl_http_statusline(data, conn);
4313 writetype |= CLIENTWRITE_STATUS;
4316 k->header = FALSE; /* this is not a header line */
4321 result = verify_header(data);
4325 result = Curl_http_header(data, conn, headp);
4330 * End of header-checks. Write them to the client.
4332 if(data->set.include_header)
4333 writetype |= CLIENTWRITE_BODY;
4334 if(k->httpcode/100 == 1)
4335 writetype |= CLIENTWRITE_1XX;
4337 Curl_debug(data, CURLINFO_HEADER_IN, headp,
4338 Curl_dyn_len(&data->state.headerb));
4340 result = Curl_client_write(data, writetype, headp,
4341 Curl_dyn_len(&data->state.headerb));
4345 data->info.header_size += Curl_dyn_len(&data->state.headerb);
4346 data->req.headerbytecount += Curl_dyn_len(&data->state.headerb);
4348 Curl_dyn_reset(&data->state.headerb);
4350 while(*k->str); /* header line within buffer */
4352 /* We might have reached the end of the header part here, but
4353 there might be a non-header part left in the end of the read
4359 #endif /* CURL_DISABLE_HTTP */