Lines Matching refs:data

103 static bool http_should_fail(struct Curl_easy *data);
162 CURLcode Curl_http_setup_conn(struct Curl_easy *data,
168 DEBUGASSERT(data->req.p.http == NULL);
174 data->req.p.http = http;
177 if(data->state.httpwant == CURL_HTTP_VERSION_3ONLY) {
178 CURLcode result = Curl_conn_may_http3(data, conn);
196 char *Curl_checkProxyheaders(struct Curl_easy *data,
203 for(head = (conn->bits.proxy && data->set.sep_headers) ?
204 data->set.proxyheaders : data->set.headers;
206 if(strncasecompare(head->data, thisheader, thislen) &&
207 Curl_headersep(head->data[thislen]))
208 return head->data;
243 /* data is in the host encoding so
272 static CURLcode http_output_basic(struct Curl_easy *data, bool proxy)
286 userp = &data->state.aptr.proxyuserpwd;
287 user = data->state.aptr.proxyuser;
288 pwd = data->state.aptr.proxypasswd;
294 userp = &data->state.aptr.userpwd;
295 user = data->state.aptr.user;
296 pwd = data->state.aptr.passwd;
336 static CURLcode http_output_bearer(struct Curl_easy *data)
341 userp = &data->state.aptr.userpwd;
344 data->set.str[STRING_BEARER]);
408 * If we have more data to send {
413 * If there is more than just a little data left to send, close
417 * If we have sent any data {
418 * If we don't have track of all the data {
427 static CURLcode http_perhapsrewind(struct Curl_easy *data,
430 struct HTTP *http = data->req.p.http;
439 switch(data->state.httpreq) {
447 bytessent = data->req.writebytecount;
451 any data then. */
459 /* figure out how much data we are expected to send */
460 switch(data->state.httpreq) {
463 if(data->state.infilesize != -1)
464 expectsend = data->state.infilesize;
475 data->state.rewindbeforesend = FALSE; /* default */
479 /* There is still data left to send */
480 if((data->state.authproxy.picked == CURLAUTH_NTLM) ||
481 (data->state.authhost.picked == CURLAUTH_NTLM) ||
482 (data->state.authproxy.picked == CURLAUTH_NTLM_WB) ||
483 (data->state.authhost.picked == CURLAUTH_NTLM_WB)) {
488 data left to send, keep on sending. */
490 /* rewind data when completely done sending! */
492 data->state.rewindbeforesend = TRUE;
493 infof(data, "Rewind stream before next send");
503 infof(data, "NTLM send, close instead of sending %"
509 /* There is still data left to send */
510 if((data->state.authproxy.picked == CURLAUTH_NEGOTIATE) ||
511 (data->state.authhost.picked == CURLAUTH_NEGOTIATE)) {
516 there is just a little (<2K) data left to send, keep on sending. */
518 /* rewind data when completely done sending! */
520 data->state.rewindbeforesend = TRUE;
521 infof(data, "Rewind stream before next send");
531 infof(data, "NEGOTIATE send, close instead of sending %"
538 streamclose(conn, "Mid-auth HTTP and much data left to send");
539 data->req.size = 0; /* don't download any more than 0 bytes */
541 /* There still is data left to send, but this connection is marked for
547 data->state.rewindbeforesend = TRUE;
548 infof(data, "Please rewind output before next send");
561 CURLcode Curl_http_auth_act(struct Curl_easy *data)
563 struct connectdata *conn = data->conn;
569 if(!data->set.str[STRING_BEARER])
572 if(100 <= data->req.httpcode && data->req.httpcode <= 199)
576 if(data->state.authproblem)
577 return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
579 if((data->state.aptr.user || data->set.str[STRING_BEARER]) &&
580 ((data->req.httpcode == 401) ||
581 (conn->bits.authneg && data->req.httpcode < 300))) {
582 pickhost = pickoneauth(&data->state.authhost, authmask);
584 data->state.authproblem = TRUE;
585 if(data->state.authhost.picked == CURLAUTH_NTLM &&
587 infof(data, "Forcing HTTP/1.1 for NTLM");
589 data->state.httpwant = CURL_HTTP_VERSION_1_1;
594 ((data->req.httpcode == 407) ||
595 (conn->bits.authneg && data->req.httpcode < 300))) {
596 pickproxy = pickoneauth(&data->state.authproxy,
599 data->state.authproblem = TRUE;
604 if((data->state.httpreq != HTTPREQ_GET) &&
605 (data->state.httpreq != HTTPREQ_HEAD) &&
606 !data->state.rewindbeforesend) {
607 result = http_perhapsrewind(data, conn);
614 Curl_safefree(data->req.newurl);
615 data->req.newurl = strdup(data->state.url); /* clone URL */
616 if(!data->req.newurl)
619 else if((data->req.httpcode < 300) &&
620 (!data->state.authhost.done) &&
626 if((data->state.httpreq != HTTPREQ_GET) &&
627 (data->state.httpreq != HTTPREQ_HEAD)) {
628 data->req.newurl = strdup(data->state.url); /* clone URL */
629 if(!data->req.newurl)
631 data->state.authhost.done = TRUE;
634 if(http_should_fail(data)) {
635 failf(data, "The requested URL returned error: %d",
636 data->req.httpcode);
649 output_auth_headers(struct Curl_easy *data,
667 result = Curl_output_aws_sigv4(data, proxy);
676 result = Curl_output_negotiate(data, conn, proxy);
685 result = Curl_output_ntlm(data, proxy);
694 result = Curl_output_ntlm_wb(data, conn, proxy);
703 result = Curl_output_digest(data,
718 !Curl_checkProxyheaders(data, conn, STRCONST("Proxy-authorization"))) ||
720 (!proxy && data->state.aptr.user &&
721 !Curl_checkheaders(data, STRCONST("Authorization")))) {
723 result = http_output_basic(data, proxy);
736 if((!proxy && data->set.str[STRING_BEARER] &&
737 !Curl_checkheaders(data, STRCONST("Authorization")))) {
739 result = http_output_bearer(data);
752 infof(data, "%s auth using %s with user '%s'",
754 proxy ? (data->state.aptr.proxyuser ?
755 data->state.aptr.proxyuser : "") :
756 (data->state.aptr.user ?
757 data->state.aptr.user : ""));
760 infof(data, "Server auth using %s with user '%s'",
761 auth, data->state.aptr.user ?
762 data->state.aptr.user : "");
775 * method. data->state.authdone is set to TRUE when authentication is
787 Curl_http_output_auth(struct Curl_easy *data,
799 DEBUGASSERT(data);
801 authhost = &data->state.authhost;
802 authproxy = &data->state.authproxy;
808 data->state.aptr.user ||
813 data->set.str[STRING_BEARER])
837 result = output_auth_headers(data, conn, authproxy, request, path, TRUE);
851 if(Curl_auth_allowed_to_host(data)
856 result = output_auth_headers(data, conn, authhost, request, path, FALSE);
877 Curl_http_output_auth(struct Curl_easy *data,
884 (void)data;
909 CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
915 struct connectdata *conn = data->conn;
930 availp = &data->info.proxyauthavail;
931 authp = &data->state.authproxy;
934 availp = &data->info.httpauthavail;
935 authp = &data->state.authhost;
968 CURLcode result = Curl_input_negotiate(data, conn, proxy, auth);
970 free(data->req.newurl);
971 data->req.newurl = strdup(data->state.url);
972 if(!data->req.newurl)
974 data->state.authproblem = FALSE;
979 data->state.authproblem = TRUE;
997 CURLcode result = Curl_input_ntlm(data, proxy, auth);
999 data->state.authproblem = FALSE;
1007 result = Curl_input_ntlm_wb(data, conn, proxy, auth);
1009 infof(data, "Authentication problem. Ignoring this.");
1010 data->state.authproblem = TRUE;
1016 infof(data, "Authentication problem. Ignoring this.");
1017 data->state.authproblem = TRUE;
1027 infof(data, "Ignoring duplicate digest auth header.");
1036 * incoming data from this header in case we are going to use
1038 result = Curl_input_digest(data, proxy, auth);
1040 infof(data, "Authentication problem. Ignoring this.");
1041 data->state.authproblem = TRUE;
1057 infof(data, "Authentication problem. Ignoring this.");
1058 data->state.authproblem = TRUE;
1072 infof(data, "Authentication problem. Ignoring this.");
1073 data->state.authproblem = TRUE;
1107 static bool http_should_fail(struct Curl_easy *data)
1110 DEBUGASSERT(data);
1111 DEBUGASSERT(data->conn);
1113 httpcode = data->req.httpcode;
1119 if(!data->set.http_fail_on_error)
1132 if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
1166 if((httpcode == 401) && !data->state.aptr.user)
1169 if((httpcode == 407) && !data->conn->bits.proxy_user_passwd)
1173 return data->state.authproblem;
1178 * data. It is used when a huge POST is to be made and the entire chunk wasn't
1180 * transfer.c loop when more data is to be sent to the peer.
1190 struct Curl_easy *data = http->backup.data;
1198 data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
1200 if(data->set.max_send_speed &&
1201 (data->set.max_send_speed < (curl_off_t)fullsize) &&
1202 (data->set.max_send_speed < http->postsize))
1204 fullsize = (size_t)data->set.max_send_speed;
1211 /* move backup data into focus and continue on that */
1214 data->state.fread_func = http->backup.fread_func;
1215 data->state.in = http->backup.fread_in;
1236 * memory. Body data may be appended to the header data if desired.
1241 struct Curl_easy *data,
1246 /* how much of the buffer contains body data */
1254 struct connectdata *conn = data->conn;
1280 if(data->set.max_send_speed &&
1281 (included_body_bytes > data->set.max_send_speed)) {
1282 curl_off_t overflow = included_body_bytes - data->set.max_send_speed;
1290 library when we attempt to re-send this buffer. Sending the same data
1292 must copy the data to the uploadbuffer first, since that is the buffer
1295 result = Curl_get_upload_buffer(data);
1302 when we speak HTTPS, as if only a fraction of it is sent now, this data
1306 if(sendsize > (size_t)data->set.upload_buffer_size)
1307 sendsize = (size_t)data->set.upload_buffer_size;
1309 memcpy(data->state.ulbuf, ptr, sendsize);
1310 ptr = data->state.ulbuf;
1331 if(data->set.max_send_speed &&
1332 (included_body_bytes > data->set.max_send_speed)) {
1333 curl_off_t overflow = included_body_bytes - data->set.max_send_speed;
1344 * and install our own `data->state.fread_func` that
1351 * amounts of data and connection filters do not like
1354 if(http && (sendsize > (size_t)data->set.upload_buffer_size))
1355 sendsize = (size_t)data->set.upload_buffer_size;
1358 result = Curl_nwrite(data, sockindex, ptr, sendsize, &amount);
1363 * number of data bytes at the end of the big buffer (out of which we may
1370 /* this data _may_ contain binary stuff */
1371 Curl_debug(data, CURLINFO_HEADER_OUT, ptr, headlen);
1373 /* there was body data sent beyond the initial header part, pass that on
1375 Curl_debug(data, CURLINFO_DATA_OUT, ptr + headlen, bodylen);
1385 data->req.writebytecount += bodylen;
1386 Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
1398 http->backup.fread_func = data->state.fread_func;
1399 http->backup.fread_in = data->state.in;
1402 http->backup.data = data;
1405 data->state.fread_func = (curl_read_callback)readmoredata;
1406 data->state.in = (void *)http;
1410 /* this much data is remaining header: */
1411 data->req.pendingheader = headersize - headlen;
1434 /* no remaining header data */
1435 data->req.pendingheader = 0;
1506 CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
1508 struct connectdata *conn = data->conn;
1514 return Curl_conn_connect(data, FIRSTSOCKET, FALSE, done);
1520 int Curl_http_getsock_do(struct Curl_easy *data,
1526 socks[0] = Curl_conn_get_socket(data, FIRSTSOCKET);
1535 CURLcode Curl_http_done(struct Curl_easy *data,
1538 struct connectdata *conn = data->conn;
1539 struct HTTP *http = data->req.p.http;
1543 data->state.authhost.multipass = FALSE;
1544 data->state.authproxy.multipass = FALSE;
1547 conn->seek_func = data->set.seek_func; /* restore */
1548 conn->seek_client = data->set.seek_client; /* restore */
1554 Curl_dyn_reset(&data->state.headerb);
1555 Curl_hyper_done(data);
1556 Curl_ws_done(data);
1564 !data->set.connect_only &&
1565 (data->req.bytecount +
1566 data->req.headerbytecount -
1567 data->req.deductheadercount) <= 0) {
1571 failf(data, "Empty reply from server");
1589 bool Curl_use_http_1_1plus(const struct Curl_easy *data,
1592 if((data->state.httpversion == 10) || (conn->httpversion == 10))
1594 if((data->state.httpwant == CURL_HTTP_VERSION_1_0) &&
1597 return ((data->state.httpwant == CURL_HTTP_VERSION_NONE) ||
1598 (data->state.httpwant >= CURL_HTTP_VERSION_1_1));
1602 static const char *get_http_string(const struct Curl_easy *data,
1605 if(Curl_conn_is_http3(data, conn, FIRSTSOCKET))
1607 if(Curl_conn_is_http2(data, conn, FIRSTSOCKET))
1609 if(Curl_use_http_1_1plus(data, conn))
1617 static CURLcode expect100(struct Curl_easy *data,
1622 if(!data->state.disableexpect && Curl_use_http_1_1plus(data, conn) &&
1627 const char *ptr = Curl_checkheaders(data, STRCONST("Expect"));
1629 data->state.expect100header =
1635 data->state.expect100header = TRUE;
1676 ptr = strchr(trailers->data, ':');
1678 result = Curl_dyn_add(b, trailers->data);
1702 CURLcode Curl_dynhds_add_custom(struct Curl_easy *data,
1706 struct connectdata *conn = data->conn;
1724 h[0] = data->set.headers;
1727 h[0] = data->set.headers;
1728 if(data->set.sep_headers) {
1729 h[1] = data->set.proxyheaders;
1734 if(data->set.sep_headers)
1735 h[0] = data->set.proxyheaders;
1737 h[0] = data->set.headers;
1742 h[0] = data->set.headers;
1755 ptr = strchr(headers->data, ':');
1757 name = headers->data;
1758 namelen = ptr - headers->data;
1772 ptr = strchr(headers->data, ';');
1780 name = headers->data;
1781 namelen = ptr - headers->data;
1798 if(data->state.aptr.host &&
1803 else if(data->state.httpreq == HTTPREQ_POST_FORM &&
1807 else if(data->state.httpreq == HTTPREQ_POST_MIME &&
1816 else if(data->state.aptr.te &&
1829 !Curl_auth_allowed_to_host(data))
1844 CURLcode Curl_add_custom_headers(struct Curl_easy *data,
1853 struct connectdata *conn = data->conn;
1871 h[0] = data->set.headers;
1874 h[0] = data->set.headers;
1875 if(data->set.sep_headers) {
1876 h[1] = data->set.proxyheaders;
1881 if(data->set.sep_headers)
1882 h[0] = data->set.proxyheaders;
1884 h[0] = data->set.headers;
1889 h[0] = data->set.headers;
1898 ptr = strchr(headers->data, ':');
1902 ptr = strchr(headers->data, ';');
1916 semicolonp = strdup(headers->data);
1924 semicolonp[ptr - headers->data] = ':';
1926 optr = &semicolonp [ptr - headers->data];
1932 if(ptr && (ptr != headers->data)) {
1942 char *compare = semicolonp ? semicolonp : headers->data;
1944 if(data->state.aptr.host &&
1949 else if(data->state.httpreq == HTTPREQ_POST_FORM &&
1953 else if(data->state.httpreq == HTTPREQ_POST_MIME &&
1962 else if(data->state.aptr.te &&
1975 !Curl_auth_allowed_to_host(data))
1979 result = Curl_hyper_header(data, req, compare);
1998 CURLcode Curl_add_timecondition(struct Curl_easy *data,
2013 if(data->set.timecondition == CURL_TIMECOND_NONE)
2017 result = Curl_gmtime(data->set.timevalue, &keeptime);
2019 failf(data, "Invalid TIMEVALUE");
2024 switch(data->set.timecondition) {
2026 DEBUGF(infof(data, "invalid time condition"));
2043 if(Curl_checkheaders(data, condp, len)) {
2070 result = Curl_hyper_header(data, req, datestr);
2077 CURLcode Curl_add_timecondition(struct Curl_easy *data,
2080 (void)data;
2086 void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
2089 Curl_HttpReq httpreq = (Curl_HttpReq)data->state.httpreq;
2092 data->state.upload)
2096 if(data->set.str[STRING_CUSTOMREQUEST])
2097 request = data->set.str[STRING_CUSTOMREQUEST];
2099 if(data->req.no_body)
2126 CURLcode Curl_http_useragent(struct Curl_easy *data)
2132 if(Curl_checkheaders(data, STRCONST("User-Agent"))) {
2133 free(data->state.aptr.uagent);
2134 data->state.aptr.uagent = NULL;
2140 CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)
2143 struct dynamically_allocated_data *aptr = &data->state.aptr;
2144 if(!data->state.this_is_a_follow) {
2146 free(data->state.first_host);
2148 data->state.first_host = strdup(conn->host.name);
2149 if(!data->state.first_host)
2152 data->state.first_remote_port = conn->remote_port;
2153 data->state.first_remote_protocol = conn->handler->protocol;
2157 ptr = Curl_checkheaders(data, STRCONST("Host"));
2158 if(ptr && (!data->state.this_is_a_follow ||
2159 strcasecompare(data->state.first_host, conn->host.name))) {
2170 /* ignore empty data */
2229 CURLcode Curl_http_target(struct Curl_easy *data,
2234 const char *path = data->state.up.path;
2235 const char *query = data->state.up.query;
2237 if(data->set.str[STRING_TARGET]) {
2238 path = data->set.str[STRING_TARGET];
2253 CURLU *h = curl_url_dup(data->state.uh);
2270 if(strcasecompare("http", data->state.up.scheme)) {
2293 result = Curl_dyn_add(r, data->set.str[STRING_TARGET]?
2294 data->set.str[STRING_TARGET]:url);
2299 if(strcasecompare("ftp", data->state.up.scheme)) {
2300 if(data->set.proxy_transfer_mode) {
2315 data->state.prefer_ascii ? 'a' : 'i');
2338 CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
2343 struct HTTP *http = data->req.p.http;
2348 data->state.mimepost = &data->set.mimepost;
2354 if(!data->state.formp) {
2355 data->state.formp = calloc(1, sizeof(curl_mimepart));
2356 if(!data->state.formp)
2358 Curl_mime_cleanpart(data->state.formp);
2359 result = Curl_getformdata(data, data->state.formp, data->set.httppost,
2360 data->state.fread_func);
2362 Curl_safefree(data->state.formp);
2365 data->state.mimepost = data->state.formp;
2370 data->state.mimepost = NULL;
2374 if(data->state.mimepost) {
2375 const char *cthdr = Curl_checkheaders(data, STRCONST("Content-Type"));
2378 data->state.mimepost->flags |= MIME_BODY_ONLY;
2385 else if(data->state.mimepost->kind == MIMEKIND_MULTIPART)
2386 cthdr = "multipart/form-data";
2388 curl_mime_headers(data->state.mimepost, data->set.headers, 0);
2389 result = Curl_mime_prepare_headers(data, data->state.mimepost, cthdr,
2391 curl_mime_headers(data->state.mimepost, NULL, 0);
2393 result = Curl_mime_rewind(data->state.mimepost);
2396 http->postsize = Curl_mime_size(data->state.mimepost);
2400 ptr = Curl_checkheaders(data, STRCONST("Transfer-Encoding"));
2403 data->req.upload_chunky =
2411 ((data->state.upload || httpreq == HTTPREQ_POST) &&
2412 data->state.infilesize == -1))) {
2416 else if(Curl_use_http_1_1plus(data, conn)) {
2419 data->req.upload_chunky = TRUE;
2422 failf(data, "Chunky upload is not supported by HTTP 1.0");
2428 data->req.upload_chunky = FALSE;
2431 if(data->req.upload_chunky)
2437 static CURLcode addexpect(struct Curl_easy *data, struct connectdata *conn,
2440 data->state.expect100header = FALSE;
2442 if(data->req.upgr101 == UPGR101_INIT) {
2443 struct HTTP *http = data->req.p.http;
2448 char *ptr = Curl_checkheaders(data, STRCONST("Expect"));
2450 data->state.expect100header =
2455 return expect100(data, conn, r);
2460 CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
2471 struct HTTP *http = data->req.p.http;
2474 case HTTPREQ_PUT: /* Let's PUT the data to the server! */
2479 http->postsize = data->state.infilesize;
2481 if((http->postsize != -1) && !data->req.upload_chunky &&
2483 !Curl_checkheaders(data, STRCONST("Content-Length")))) {
2491 result = addexpect(data, conn, r);
2501 Curl_pgrsSetUploadSize(data, http->postsize);
2504 result = Curl_buffer_send(r, data, data->req.p.http,
2505 &data->info.request_size, 0,
2508 failf(data, "Failed sending PUT request");
2511 Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
2519 /* This is form posting using mime data. */
2526 result = Curl_buffer_send(r, data, data->req.p.http,
2527 &data->info.request_size, 0,
2530 failf(data, "Failed sending POST request");
2533 Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
2537 data->state.infilesize = http->postsize;
2540 we don't upload data chunked, as RFC2616 forbids us to set both
2542 if(http->postsize != -1 && !data->req.upload_chunky &&
2543 (!Curl_checkheaders(data, STRCONST("Content-Length")))) {
2558 for(hdr = data->state.mimepost->curlheaders; hdr; hdr = hdr->next) {
2559 result = Curl_dyn_addf(r, "%s\r\n", hdr->data);
2566 result = addexpect(data, conn, r);
2576 Curl_pgrsSetUploadSize(data, http->postsize);
2579 data->state.fread_func = (curl_read_callback) Curl_mime_read;
2580 data->state.in = (void *) data->state.mimepost;
2584 result = Curl_buffer_send(r, data, data->req.p.http,
2585 &data->info.request_size, 0,
2588 failf(data, "Failed sending POST request");
2591 Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
2605 http->postsize = data->state.infilesize;
2608 we don't upload data chunked, as RFC2616 forbids us to set both
2610 if((http->postsize != -1) && !data->req.upload_chunky &&
2612 !Curl_checkheaders(data, STRCONST("Content-Length")))) {
2621 if(!Curl_checkheaders(data, STRCONST("Content-Type"))) {
2628 result = addexpect(data, conn, r);
2634 if(data->set.postfields) {
2635 if(!data->state.expect100header &&
2640 then append the post data to the HTTP request header. This limit
2642 get the data duplicated with malloc() and family. */
2649 if(!data->req.upload_chunky) {
2652 result = Curl_dyn_addn(r, data->set.postfields,
2659 /* Append the POST data chunky-style */
2664 result = Curl_dyn_addn(r, data->set.postfields,
2680 Curl_pgrsSetUploadSize(data, http->postsize);
2683 /* A huge POST coming up, do data separate from the request */
2684 http->postdata = data->set.postfields;
2686 http->backup.data = data;
2687 data->state.fread_func = (curl_read_callback)readmoredata;
2688 data->state.in = (void *)http;
2691 Curl_pgrsSetUploadSize(data, http->postsize);
2707 if(data->req.upload_chunky && conn->bits.authneg) {
2709 end-of-data only */
2716 else if(data->state.infilesize) {
2718 Curl_pgrsSetUploadSize(data, http->postsize?http->postsize:-1);
2727 result = Curl_buffer_send(r, data, data->req.p.http,
2728 &data->info.request_size, included_body,
2732 failf(data, "Failed sending HTTP POST request");
2734 Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
2744 result = Curl_buffer_send(r, data, data->req.p.http,
2745 &data->info.request_size, 0,
2748 failf(data, "Failed sending HTTP request");
2751 !(data->set.connect_only))
2753 request probably wants to send data too post upgrade */
2754 Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, FIRSTSOCKET);
2758 Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
2766 CURLcode Curl_http_cookies(struct Curl_easy *data,
2773 if(data->set.str[STRING_COOKIE] &&
2774 !Curl_checkheaders(data, STRCONST("Cookie")))
2775 addcookies = data->set.str[STRING_COOKIE];
2777 if(data->cookies || addcookies) {
2781 if(data->cookies && data->state.cookie_engine) {
2782 const char *host = data->state.aptr.cookiehost ?
2783 data->state.aptr.cookiehost : conn->host.name;
2789 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
2790 co = Curl_cookie_getlist(data, data->cookies, host, data->state.up.path,
2792 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
2808 infof(data, "Restricted outgoing cookies due to header size, "
2842 CURLcode Curl_http_range(struct Curl_easy *data,
2845 if(data->state.use_range) {
2852 !Curl_checkheaders(data, STRCONST("Range"))) {
2854 free(data->state.aptr.rangeline);
2855 data->state.aptr.rangeline = aprintf("Range: bytes=%s\r\n",
2856 data->state.range);
2859 !Curl_checkheaders(data, STRCONST("Content-Range"))) {
2862 free(data->state.aptr.rangeline);
2864 if(data->set.set_resume_from < 0) {
2868 data->state.aptr.rangeline =
2871 data->state.infilesize - 1, data->state.infilesize);
2874 else if(data->state.resume_from) {
2877 data->state.resume_from + data->state.infilesize;
2878 data->state.aptr.rangeline =
2881 data->state.range, total_expected_size-1,
2887 data->state.aptr.rangeline =
2889 data->state.range, data->state.infilesize);
2891 if(!data->state.aptr.rangeline)
2898 CURLcode Curl_http_resume(struct Curl_easy *data,
2903 data->state.resume_from) {
2913 if(data->state.resume_from < 0) {
2918 data->state.resume_from = 0;
2921 if(data->state.resume_from && !data->state.followlocation) {
2928 Curl_set_in_callback(data, true);
2929 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
2931 Curl_set_in_callback(data, false);
2938 failf(data, "Could not seek stream");
2945 (data->state.resume_from - passed > (curl_off_t)sizeof(scratch)) ?
2947 curlx_sotouz(data->state.resume_from - passed);
2950 data->state.fread_func(scratch, 1, readthisamountnow,
2951 data->state.in);
2957 failf(data, "Could only read %" CURL_FORMAT_CURL_OFF_T
2961 } while(passed < data->state.resume_from);
2965 if(data->state.infilesize>0) {
2966 data->state.infilesize -= data->state.resume_from;
2968 if(data->state.infilesize <= 0) {
2969 failf(data, "File already completely uploaded");
2979 CURLcode Curl_http_firstwrite(struct Curl_easy *data,
2983 struct SingleRequest *k = &data->req;
2986 if(data->req.newurl) {
2997 infof(data, "Ignoring the response-body");
2999 if(data->state.resume_from && !k->content_range &&
3000 (data->state.httpreq == HTTPREQ_GET) &&
3003 if(k->size == data->state.resume_from) {
3006 infof(data, "The entire document is already downloaded");
3017 failf(data, "HTTP server doesn't seem to support "
3022 if(data->set.timecondition && !data->state.range) {
3027 if(!Curl_meets_timecondition(data, k->timeofdoc)) {
3031 data->info.httpcode = 304;
3032 infof(data, "Simulate an HTTP 304 response");
3044 CURLcode Curl_transferencode(struct Curl_easy *data)
3046 if(!Curl_checkheaders(data, STRCONST("TE")) &&
3047 data->set.http_transfer_encoding) {
3053 char *cptr = Curl_checkheaders(data, STRCONST("Connection"));
3056 Curl_safefree(data->state.aptr.te);
3065 data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
3069 if(!data->state.aptr.te)
3082 CURLcode Curl_http(struct Curl_easy *data, bool *done)
3084 struct connectdata *conn = data->conn;
3102 DEBUGASSERT(Curl_conn_is_http3(data, conn, FIRSTSOCKET));
3106 if(!Curl_conn_is_http2(data, conn, FIRSTSOCKET) &&
3109 result = Curl_http2_switch(data, conn, FIRSTSOCKET);
3115 DEBUGASSERT(Curl_conn_is_http2(data, conn, FIRSTSOCKET));
3122 if(Curl_http2_may_switch(data, conn, FIRSTSOCKET)) {
3123 DEBUGF(infof(data, "HTTP/2 over clean TCP"));
3124 result = Curl_http2_switch(data, conn, FIRSTSOCKET);
3131 http = data->req.p.http;
3134 result = Curl_http_host(data, conn);
3138 result = Curl_http_useragent(data);
3142 Curl_http_method(data, conn, &request, &httpreq);
3147 if(data->state.up.query) {
3148 pq = aprintf("%s?%s", data->state.up.path, data->state.up.query);
3152 result = Curl_http_output_auth(data, conn, request, httpreq,
3153 (pq ? pq : data->state.up.path), FALSE);
3159 Curl_safefree(data->state.aptr.ref);
3160 if(data->state.referer && !Curl_checkheaders(data, STRCONST("Referer"))) {
3161 data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer);
3162 if(!data->state.aptr.ref)
3166 if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) &&
3167 data->set.str[STRING_ENCODING]) {
3168 Curl_safefree(data->state.aptr.accept_encoding);
3169 data->state.aptr.accept_encoding =
3170 aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
3171 if(!data->state.aptr.accept_encoding)
3175 Curl_safefree(data->state.aptr.accept_encoding);
3179 result = Curl_transferencode(data);
3184 result = Curl_http_body(data, conn, httpreq, &te);
3188 p_accept = Curl_checkheaders(data,
3191 result = Curl_http_resume(data, conn, httpreq);
3195 result = Curl_http_range(data, httpreq);
3199 httpstring = get_http_string(data, conn);
3206 Curl_dyn_reset(&data->state.headerb);
3212 result = Curl_http_target(data, conn, &req);
3219 if(conn->bits.altused && !Curl_checkheaders(data, STRCONST("Alt-Used"))) {
3245 (data->state.aptr.host?data->state.aptr.host:""),
3246 data->state.aptr.proxyuserpwd?
3247 data->state.aptr.proxyuserpwd:"",
3248 data->state.aptr.userpwd?data->state.aptr.userpwd:"",
3249 (data->state.use_range && data->state.aptr.rangeline)?
3250 data->state.aptr.rangeline:"",
3251 (data->set.str[STRING_USERAGENT] &&
3252 *data->set.str[STRING_USERAGENT] &&
3253 data->state.aptr.uagent)?
3254 data->state.aptr.uagent:"",
3256 data->state.aptr.te?data->state.aptr.te:"",
3257 (data->set.str[STRING_ENCODING] &&
3258 *data->set.str[STRING_ENCODING] &&
3259 data->state.aptr.accept_encoding)?
3260 data->state.aptr.accept_encoding:"",
3261 (data->state.referer && data->state.aptr.ref)?
3262 data->state.aptr.ref:"" /* Referer: <data> */,
3266 !Curl_checkheaders(data, STRCONST("Proxy-Connection")) &&
3267 !Curl_checkProxyheaders(data,
3280 Curl_safefree(data->state.aptr.userpwd);
3281 Curl_safefree(data->state.aptr.proxyuserpwd);
3291 (data->state.httpwant == CURL_HTTP_VERSION_2)) {
3294 result = Curl_http2_request_upgrade(&req, data);
3301 result = Curl_http_cookies(data, conn, &req);
3304 result = Curl_ws_request(data, &req);
3307 result = Curl_add_timecondition(data, &req);
3309 result = Curl_add_custom_headers(data, FALSE, &req);
3315 Curl_pgrsSetUploadSize(data, 0); /* nothing */
3318 result = Curl_http_bodysend(data, conn, &req, httpreq);
3326 (http->postsize <= data->req.writebytecount) &&
3328 data->req.upload_done = TRUE;
3330 if(data->req.writebytecount) {
3333 Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
3334 if(Curl_pgrsUpdate(data))
3340 infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
3342 data->req.writebytecount, http->postsize);
3343 data->req.upload_done = TRUE;
3344 data->req.keepon &= ~KEEP_SEND; /* we're done writing */
3345 data->req.exp100 = EXP100_SEND_DATA; /* already sent */
3346 Curl_expire_done(data, EXPIRE_100_TIMEOUT);
3350 if(data->req.upload_done)
3351 Curl_conn_ev_data_done_send(data);
3353 if((conn->httpversion >= 20) && data->req.upload_chunky)
3357 data->req.upload_chunky = FALSE;
3360 failf(data, "HTTP request too large");
3367 STATUS_UNKNOWN, /* not enough data to tell yet */
3386 checkhttpprefix(struct Curl_easy *data,
3389 struct curl_slist *head = data->set.http200aliases;
3394 if(checkprefixmax(head->data, s, len)) {
3409 checkrtspprefix(struct Curl_easy *data,
3414 (void)data; /* unused */
3423 checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
3428 return checkrtspprefix(data, s, len);
3433 return checkhttpprefix(data, s, len);
3439 CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
3443 struct SingleRequest *k = &data->req;
3446 !data->set.ignorecl && checkprefix("Content-Length:", headp)) {
3457 if(data->set.max_filesize) {
3458 failf(data, "Maximum file size exceeded");
3462 infof(data, "Overflow Content-Length: value");
3466 failf(data, "Invalid Content-Length: value");
3476 /* ignore empty data */
3479 Curl_safefree(data->info.contenttype);
3480 data->info.contenttype = contenttype;
3496 infof(data, "HTTP/1.0 proxy connection set to keep alive");
3508 infof(data, "HTTP/1.1 proxy connection set close");
3522 infof(data, "HTTP/1.0 connection set to keep alive");
3541 * coming block) (terminated with CRLF), then a block of data
3543 * of chunks, and a chunk-data set to zero signals the
3546 result = Curl_build_unencoding_stack(data,
3551 if(!k->chunk && data->set.http_transfer_encoding) {
3559 data->set.str[STRING_ENCODING]) {
3567 result = Curl_build_unencoding_stack(data,
3585 data->info.retry_after = retry_after; /* store it */
3608 if(data->state.resume_from == k->offset)
3614 data->state.resume_from = 0; /* get everything */
3617 else if(data->cookies && data->state.cookie_engine &&
3621 const char *host = data->state.aptr.cookiehost?
3622 data->state.aptr.cookiehost:conn->host.name;
3629 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
3631 Curl_cookie_add(data, data->cookies, TRUE, FALSE,
3633 data->state.up.path, secure_context);
3634 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
3638 (data->set.timecondition || data->set.get_filetime) ) {
3640 if(data->set.get_filetime)
3641 data->info.filetime = k->timeofdoc;
3653 result = Curl_http_input_auth(data, proxy, auth);
3663 struct auth *authp = &data->state.authhost;
3671 infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
3679 !data->req.location) {
3685 /* ignore empty data */
3688 data->req.location = location;
3690 if(data->set.http_follow_location) {
3691 DEBUGASSERT(!data->req.newurl);
3692 data->req.newurl = strdup(data->req.location); /* clone */
3693 if(!data->req.newurl)
3696 /* some cases of POST and PUT etc needs to rewind the data
3698 result = http_perhapsrewind(data, conn);
3703 data->state.this_is_a_follow = TRUE;
3710 else if(data->hsts && checkprefix("Strict-Transport-Security:", headp) &&
3720 Curl_hsts_parse(data->hsts, conn->host.name,
3723 infof(data, "Illegal STS header skipped");
3726 infof(data, "Parsed STS header fine (%zu entries)",
3727 data->hsts->list.size);
3733 else if(data->asi && checkprefix("Alt-Svc:", headp) &&
3745 result = Curl_altsvc_parse(data, data->asi,
3754 result = Curl_rtsp_parseheader(data, headp);
3766 CURLcode Curl_http_statusline(struct Curl_easy *data,
3769 struct SingleRequest *k = &data->req;
3770 data->info.httpcode = k->httpcode;
3772 data->info.httpversion = conn->httpversion;
3773 if(!data->state.httpversion ||
3774 data->state.httpversion > conn->httpversion)
3776 data->state.httpversion = conn->httpversion;
3786 if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
3790 k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
3797 infof(data, "HTTP 1.0, assume close after body");
3802 DEBUGF(infof(data, "HTTP/2 found, allow multiplexing"));
3810 DEBUGF(infof(data,
3821 if(data->set.timecondition)
3822 data->info.timecond = TRUE;
3845 CURLcode Curl_http_size(struct Curl_easy *data)
3847 struct SingleRequest *k = &data->req;
3848 if(data->req.ignore_cl || k->chunk) {
3852 if(data->set.max_filesize &&
3853 k->size > data->set.max_filesize) {
3854 failf(data, "Maximum file size exceeded");
3857 Curl_pgrsSetDownloadSize(data, k->size);
3863 static CURLcode verify_header(struct Curl_easy *data)
3865 struct SingleRequest *k = &data->req;
3866 const char *header = Curl_dyn_ptr(&data->state.headerb);
3867 size_t hlen = Curl_dyn_len(&data->state.headerb);
3871 failf(data, "Nul byte in header");
3884 failf(data, "Header without colon");
3891 CURLcode Curl_bump_headersize(struct Curl_easy *data,
3898 data->info.header_size += (unsigned int)delta;
3899 data->req.allheadercount += (unsigned int)delta;
3901 data->req.headerbytecount += (unsigned int)delta;
3902 if(data->req.allheadercount > max)
3903 bad = data->req.allheadercount;
3904 else if(data->info.header_size > (max * 20)) {
3905 bad = data->info.header_size;
3910 bad = data->req.allheadercount + delta;
3912 failf(data, "Too large response headers: %zu > %u", bad, max);
3922 static CURLcode http_rw_headers(struct Curl_easy *data,
3926 struct connectdata *conn = data->conn;
3928 struct SingleRequest *k = &data->req;
3939 /* data is in network encoding so use 0x0a instead of '\n' */
3943 /* Not a complete header line within buffer, append the data to
3945 result = Curl_dyn_addn(&data->state.headerb, buf, blen);
3953 checkprotoprefix(data, conn,
3954 Curl_dyn_ptr(&data->state.headerb),
3955 Curl_dyn_len(&data->state.headerb));
3961 if(!data->set.http09_allowed) {
3962 failf(data, "Received HTTP/0.9 when not allowed");
3974 result = Curl_dyn_addn(&data->state.headerb, buf, line_length);
3988 statusline st = checkprotoprefix(data, conn,
3989 Curl_dyn_ptr(&data->state.headerb),
3990 Curl_dyn_len(&data->state.headerb));
3994 if(!data->set.http09_allowed) {
3995 failf(data, "Received HTTP/0.9 when not allowed");
4006 headp = Curl_dyn_ptr(&data->state.headerb);
4024 * to receive the data.
4035 Curl_expire_done(data, EXPIRE_100_TIMEOUT);
4043 infof(data, "Received 101, Switching to HTTP/2");
4054 result = Curl_ws_accept(data, buf, blen);
4058 *pconsumed += blen; /* ws accept handled the data */
4060 if(data->set.connect_only)
4071 failf(data, "unexpected 101 response code");
4087 Curl_multi_connchanged(data->multi);
4094 data->state.httpreq != HTTPREQ_HEAD) {
4100 infof(data, "no chunk, no close, no size. Assume close to "
4107 result = Curl_http_size(data);
4116 (((data->req.httpcode == 401) &&
4118 ((data->req.httpcode == 407) &&
4120 infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
4121 data->state.authproblem = TRUE;
4126 (((data->req.httpcode == 401) &&
4128 ((data->req.httpcode == 407) &&
4130 infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
4131 data->state.authproblem = TRUE;
4134 (data->req.httpcode != 401)) {
4138 (data->req.httpcode != 407)) {
4148 headerlen = Curl_dyn_len(&data->state.headerb);
4149 result = Curl_client_write(data, writetype,
4150 Curl_dyn_ptr(&data->state.headerb),
4155 result = Curl_bump_headersize(data, headerlen, FALSE);
4163 if(http_should_fail(data)) {
4164 failf(data, "The requested URL returned error: %d",
4172 if(data->req.upgr101 == UPGR101_WS) {
4173 failf(data, "Refused WebSockets upgrade: %d", k->httpcode);
4179 data->req.deductheadercount =
4180 (100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
4185 result = Curl_http_auth_act(data);
4192 !data->state.rewindbeforesend) {
4194 * General treatment of errors when about to send data. Including :
4206 switch(data->state.httpreq) {
4215 Curl_expire_done(data, EXPIRE_100_TIMEOUT);
4217 if((k->httpcode == 417) && data->state.expect100header) {
4222 infof(data, "Got HTTP failure 417 while waiting for a 100");
4225 infof(data, "Got HTTP failure 417 while sending data");
4227 "Stop sending data before everything sent");
4228 result = http_perhapsrewind(data, conn);
4232 data->state.disableexpect = TRUE;
4233 DEBUGASSERT(!data->req.newurl);
4234 data->req.newurl = strdup(data->state.url);
4235 Curl_done_sending(data, k);
4237 else if(data->set.http_keep_sending_on_error) {
4238 infof(data, "HTTP error before end of send, keep sending");
4245 infof(data, "HTTP error before end of send, stop sending");
4246 streamclose(conn, "Stop sending data before everything sent");
4247 result = Curl_done_sending(data, k);
4251 if(data->state.expect100header)
4262 if(data->state.rewindbeforesend &&
4265 infof(data, "Keep sending data to get tossed away");
4277 if(data->req.no_body)
4286 && !Curl_conn_is_http2(data, conn, FIRSTSOCKET)
4287 && !Curl_conn_is_http3(data, conn, FIRSTSOCKET))
4290 Curl_debug(data, CURLINFO_HEADER_IN,
4291 Curl_dyn_ptr(&data->state.headerb),
4292 Curl_dyn_len(&data->state.headerb));
4297 Curl_dyn_reset(&data->state.headerb);
4302 result = Curl_http2_upgrade(data, conn, FIRSTSOCKET, buf, blen);
4353 failf(data, "Unsupported HTTP/1 subversion in response");
4373 failf(data, "Unsupported HTTP version in response");
4380 failf(data, "Unsupported response code in HTTP response");
4395 failf(data, "Unsupported HTTP version (%u.%d) in response",
4403 infof(data, "Lying server, not serving HTTP/2");
4414 checkhttpprefix(data,
4415 Curl_dyn_ptr(&data->state.headerb),
4416 Curl_dyn_len(&data->state.headerb));
4453 result = Curl_http_statusline(data, conn);
4464 result = verify_header(data);
4468 result = Curl_http_header(data, conn, headp);
4478 Curl_debug(data, CURLINFO_HEADER_IN, headp,
4479 Curl_dyn_len(&data->state.headerb));
4481 result = Curl_client_write(data, writetype, headp,
4482 Curl_dyn_len(&data->state.headerb));
4486 result = Curl_bump_headersize(data, Curl_dyn_len(&data->state.headerb),
4491 Curl_dyn_reset(&data->state.headerb);
4500 Curl_dyn_free(&data->state.headerb);
4507 * when not done yet and otherwise return without consuming data.
4509 CURLcode Curl_http_write_resp_hds(struct Curl_easy *data,
4515 if(!data->req.header) {
4522 result = http_rw_headers(data, buf, blen, pconsumed);
4523 if(!result && !data->req.header) {
4525 result = Curl_http_firstwrite(data, data->conn, done);
4527 if(!data->req.no_body && Curl_dyn_len(&data->state.headerb)) {
4531 result = Curl_client_write(data, CLIENTWRITE_BODY,
4532 Curl_dyn_ptr(&data->state.headerb),
4533 Curl_dyn_len(&data->state.headerb));
4535 Curl_dyn_free(&data->state.headerb);
4541 CURLcode Curl_http_write_resp(struct Curl_easy *data,
4551 result = Curl_http_write_resp_hds(data, buf, blen, &consumed, done);
4558 /* either all was consumed in header parsing, or we have data left
4559 * and are done with heders, e.g. it is BODY data */
4560 DEBUGASSERT(!blen || !data->req.header);
4561 if(!data->req.header && (blen || is_eos)) {
4562 /* BODY data after header been parsed, write and consume */
4566 result = Curl_client_write(data, flags, (char *)buf, blen);
4838 struct httpreq *req, struct Curl_easy *data)
4852 scheme = Curl_checkheaders(data, STRCONST(HTTP_PSEUDO_SCHEME));
4857 infof(data, "set pseudo header %s to %s", HTTP_PSEUDO_SCHEME, scheme);
4860 scheme = (data->conn && data->conn->handler->flags & PROTOPT_SSL)?