* Called after the first HTTP response line (the status line) has been
* received and parsed.
*/
-
CURLcode Curl_http_statusline(struct Curl_easy *data,
struct connectdata *conn)
{
struct SingleRequest *k = &data->req;
+
+ switch(k->httpversion) {
+ case 10:
+ case 11:
+#ifdef USE_HTTP2
+ case 20:
+#endif
+#ifdef ENABLE_QUIC
+ case 30:
+#endif
+ /* TODO: we should verify that responses do not switch major
+ * HTTP version of the connection. Now, it seems we might accept
+ * a HTTP/2 response on a HTTP/1.1 connection, which is wrong. */
+ conn->httpversion = (unsigned char)k->httpversion;
+ break;
+ default:
+ failf(data, "Unsupported HTTP version (%u.%d) in response",
+ k->httpversion/10, k->httpversion%10);
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+
data->info.httpcode = k->httpcode;
+ data->info.httpversion = k->httpversion;
+ conn->httpversion = (unsigned char)k->httpversion;
- data->info.httpversion = conn->httpversion;
- if(!data->state.httpversion ||
- data->state.httpversion > conn->httpversion)
+ if(!data->state.httpversion || data->state.httpversion > k->httpversion)
/* store the lowest server version we encounter */
- data->state.httpversion = conn->httpversion;
+ data->state.httpversion = (unsigned char)k->httpversion;
/*
* This code executes as part of processing the header. As a
k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
}
- if(conn->httpversion == 10) {
+ if(k->httpversion == 10) {
/* Default action for HTTP/1.0 must be to close, unless
we get one of those fancy headers that tell us the
server keeps it open for us! */
infof(data, "HTTP 1.0, assume close after body");
connclose(conn, "HTTP/1.0 close after body");
}
- else if(conn->httpversion == 20 ||
+ else if(k->httpversion == 20 ||
(k->upgr101 == UPGR101_H2 && k->httpcode == 101)) {
DEBUGF(infof(data, "HTTP/2 found, allow multiplexing"));
/* HTTP/2 cannot avoid multiplexing since it is a core functionality
of the protocol */
conn->bundle->multiuse = BUNDLE_MULTIPLEX;
}
- else if(conn->httpversion >= 11 &&
- !conn->bits.close) {
+ else if(k->httpversion >= 11 && !conn->bits.close) {
/* If HTTP version is >= 1.1 and connection is persistent */
- DEBUGF(infof(data,
- "HTTP 1.1 or later with persistent connection"));
+ DEBUGF(infof(data, "HTTP 1.1 or later with persistent connection"));
}
k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200;
}
+static CURLcode http_on_response(struct Curl_easy *data,
+ const char *buf, size_t blen,
+ size_t *pconsumed)
+{
+ struct connectdata *conn = data->conn;
+ CURLcode result = CURLE_OK;
+ struct SingleRequest *k = &data->req;
+ bool switch_to_h2 = FALSE;
+
+ (void)buf; /* not used without HTTP2 enabled */
+ *pconsumed = 0;
+
+ if(k->upgr101 == UPGR101_RECEIVED) {
+ /* supposedly upgraded to http2 now */
+ if(conn->httpversion != 20)
+ infof(data, "Lying server, not serving HTTP/2");
+ }
+ if(conn->httpversion < 20) {
+ conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
+ }
+
+ if(k->httpcode < 100) {
+ failf(data, "Unsupported response code in HTTP response");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+ else if(k->httpcode < 200) {
+ /* "A user agent MAY ignore unexpected 1xx status responses." */
+ switch(k->httpcode) {
+ case 100:
+ /*
+ * We have made an HTTP PUT or POST and this is 1.1-lingo
+ * that tells us that the server is OK with this and ready
+ * to receive the data.
+ * However, we'll get more headers now so we must get
+ * back into the header-parsing state!
+ */
+ k->header = TRUE;
+ k->headerline = 0; /* restart the header line counter */
+
+ /* if we did wait for this do enable write now! */
+ Curl_http_exp100_got100(data);
+ break;
+ case 101:
+ if(conn->httpversion == 11) {
+ /* Switching Protocols only allowed from HTTP/1.1 */
+ if(k->upgr101 == UPGR101_H2) {
+ /* Switching to HTTP/2 */
+ infof(data, "Received 101, Switching to HTTP/2");
+ k->upgr101 = UPGR101_RECEIVED;
+
+ /* we'll get more headers (HTTP/2 response) */
+ k->header = TRUE;
+ k->headerline = 0; /* restart the header line counter */
+ switch_to_h2 = TRUE;
+ }
+#ifdef USE_WEBSOCKETS
+ else if(k->upgr101 == UPGR101_WS) {
+ /* verify the response */
+ result = Curl_ws_accept(data, buf, blen);
+ if(result)
+ return result;
+ k->header = FALSE; /* no more header to parse! */
+ *pconsumed += blen; /* ws accept handled the data */
+ blen = 0;
+ if(data->set.connect_only)
+ k->keepon &= ~KEEP_RECV; /* read no more content */
+ }
+#endif
+ else {
+ /* Not switching to another protocol */
+ k->header = FALSE; /* no more header to parse! */
+ }
+ }
+ else {
+ /* invalid for other HTTP versions */
+ failf(data, "unexpected 101 response code");
+ return CURLE_WEIRD_SERVER_REPLY;
+ }
+ break;
+ default:
+ /* the status code 1xx indicates a provisional response, so
+ we'll get another set of headers */
+ k->header = TRUE;
+ k->headerline = 0; /* restart the header line counter */
+ break;
+ }
+ }
+ else {
+ /* k->httpcode >= 200, final response */
+ k->header = FALSE;
+
+ if(k->upgr101 == UPGR101_H2) {
+ /* A requested upgrade was denied, poke the multi handle to possibly
+ allow a pending pipewait to continue */
+ Curl_multi_connchanged(data->multi);
+ }
+
+ if((k->size == -1) && !k->chunk && !conn->bits.close &&
+ (conn->httpversion == 11) &&
+ !(conn->handler->protocol & CURLPROTO_RTSP) &&
+ data->state.httpreq != HTTPREQ_HEAD) {
+ /* On HTTP 1.1, when connection is not to get closed, but no
+ Content-Length nor Transfer-Encoding chunked have been
+ received, according to RFC2616 section 4.4 point 5, we
+ assume that the server will close the connection to
+ signal the end of the document. */
+ infof(data, "no chunk, no close, no size. Assume close to "
+ "signal end");
+ streamclose(conn, "HTTP: No end-of-message indicator");
+ }
+ }
+
+ if(!k->header) {
+ result = Curl_http_size(data);
+ if(result)
+ return result;
+ }
+
+ /* At this point we have some idea about the fate of the connection.
+ If we are closing the connection it may result auth failure. */
+#if defined(USE_NTLM)
+ if(conn->bits.close &&
+ (((data->req.httpcode == 401) &&
+ (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
+ ((data->req.httpcode == 407) &&
+ (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
+ infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
+ data->state.authproblem = TRUE;
+ }
+#endif
+#if defined(USE_SPNEGO)
+ if(conn->bits.close &&
+ (((data->req.httpcode == 401) &&
+ (conn->http_negotiate_state == GSS_AUTHRECV)) ||
+ ((data->req.httpcode == 407) &&
+ (conn->proxy_negotiate_state == GSS_AUTHRECV)))) {
+ infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
+ data->state.authproblem = TRUE;
+ }
+ if((conn->http_negotiate_state == GSS_AUTHDONE) &&
+ (data->req.httpcode != 401)) {
+ conn->http_negotiate_state = GSS_AUTHSUCC;
+ }
+ if((conn->proxy_negotiate_state == GSS_AUTHDONE) &&
+ (data->req.httpcode != 407)) {
+ conn->proxy_negotiate_state = GSS_AUTHSUCC;
+ }
+#endif
+
+ /*
+ * When all the headers have been parsed, see if we should give
+ * up and return an error.
+ */
+ if(http_should_fail(data)) {
+ failf(data, "The requested URL returned error: %d",
+ k->httpcode);
+ return CURLE_HTTP_RETURNED_ERROR;
+ }
+
+#ifdef USE_WEBSOCKETS
+ /* All non-101 HTTP status codes are bad when wanting to upgrade to
+ websockets */
+ if(data->req.upgr101 == UPGR101_WS) {
+ failf(data, "Refused WebSockets upgrade: %d", k->httpcode);
+ return CURLE_HTTP_RETURNED_ERROR;
+ }
+#endif
+
+
+ /* Curl_http_auth_act() checks what authentication methods
+ * that are available and decides which one (if any) to
+ * use. It will set 'newurl' if an auth method was picked. */
+ result = Curl_http_auth_act(data);
+
+ if(result)
+ return result;
+
+ if(k->httpcode >= 300) {
+ if((!data->req.authneg) && !conn->bits.close &&
+ !Curl_creader_will_rewind(data)) {
+ /*
+ * General treatment of errors when about to send data. Including :
+ * "417 Expectation Failed", while waiting for 100-continue.
+ *
+ * The check for close above is done simply because of something
+ * else has already deemed the connection to get closed then
+ * something else should've considered the big picture and we
+ * avoid this check.
+ *
+ * rewindbeforesend indicates that something has told libcurl to
+ * continue sending even if it gets discarded
+ */
+
+ switch(data->state.httpreq) {
+ case HTTPREQ_PUT:
+ case HTTPREQ_POST:
+ case HTTPREQ_POST_FORM:
+ case HTTPREQ_POST_MIME:
+ /* We got an error response. If this happened before the whole
+ * request body has been sent we stop sending and mark the
+ * connection for closure after we've read the entire response.
+ */
+ if(!Curl_req_done_sending(data)) {
+ if((k->httpcode == 417) && Curl_http_exp100_is_selected(data)) {
+ /* 417 Expectation Failed - try again without the Expect
+ header */
+ if(!k->writebytecount && http_exp100_is_waiting(data)) {
+ infof(data, "Got HTTP failure 417 while waiting for a 100");
+ }
+ else {
+ infof(data, "Got HTTP failure 417 while sending data");
+ streamclose(conn,
+ "Stop sending data before everything sent");
+ result = http_perhapsrewind(data, conn);
+ if(result)
+ return result;
+ }
+ data->state.disableexpect = TRUE;
+ DEBUGASSERT(!data->req.newurl);
+ data->req.newurl = strdup(data->state.url);
+ Curl_req_abort_sending(data);
+ }
+ else if(data->set.http_keep_sending_on_error) {
+ infof(data, "HTTP error before end of send, keep sending");
+ http_exp100_send_anyway(data);
+ }
+ else {
+ infof(data, "HTTP error before end of send, stop sending");
+ streamclose(conn, "Stop sending data before everything sent");
+ result = Curl_req_abort_sending(data);
+ if(result)
+ return result;
+ }
+ }
+ break;
+
+ default: /* default label present to avoid compiler warnings */
+ break;
+ }
+ }
+
+ if(Curl_creader_will_rewind(data) && !Curl_req_done_sending(data)) {
+ /* We rewind before next send, continue sending now */
+ infof(data, "Keep sending data to get tossed away");
+ k->keepon |= KEEP_SEND;
+ }
+ }
+
+ if(!k->header) {
+ /*
+ * really end-of-headers.
+ *
+ * If we requested a "no body", this is a good time to get
+ * out and return home.
+ */
+ if(data->req.no_body)
+ k->download_done = TRUE;
+
+ /* If max download size is *zero* (nothing) we already have
+ nothing and can safely return ok now! But for HTTP/2, we'd
+ like to call http2_handle_stream_close to properly close a
+ stream. In order to do this, we keep reading until we
+ close the stream. */
+ if(0 == k->maxdownload
+ && !Curl_conn_is_http2(data, conn, FIRSTSOCKET)
+ && !Curl_conn_is_http3(data, conn, FIRSTSOCKET))
+ k->download_done = TRUE;
+ }
+
+ if(switch_to_h2) {
+ /* Having handled the headers, we can do the HTTP/2 switch.
+ * Any remaining `buf` bytes are already HTTP/2 and passed to
+ * be processed. */
+ result = Curl_http2_upgrade(data, conn, FIRSTSOCKET, buf, blen);
+ if(result)
+ return result;
+ *pconsumed += blen;
+ }
+
+ return CURLE_OK;
+}
/*
* Read any HTTP header lines from the server and pass them to the client app.
*/
hd = Curl_dyn_ptr(&data->state.headerb);
hdlen = Curl_dyn_len(&data->state.headerb);
if((0x0a == *hd) || (0x0d == *hd)) {
- bool switch_to_h2 = FALSE;
- /* Zero-length header line means end of headers! */
-
- if(100 <= k->httpcode && 199 >= k->httpcode) {
- /* "A user agent MAY ignore unexpected 1xx status responses." */
- switch(k->httpcode) {
- case 100:
- /*
- * We have made an HTTP PUT or POST and this is 1.1-lingo
- * that tells us that the server is OK with this and ready
- * to receive the data.
- * However, we'll get more headers now so we must get
- * back into the header-parsing state!
- */
- k->header = TRUE;
- k->headerline = 0; /* restart the header line counter */
-
- /* if we did wait for this do enable write now! */
- Curl_http_exp100_got100(data);
- break;
- case 101:
- if(conn->httpversion == 11) {
- /* Switching Protocols only allowed from HTTP/1.1 */
- if(k->upgr101 == UPGR101_H2) {
- /* Switching to HTTP/2 */
- infof(data, "Received 101, Switching to HTTP/2");
- k->upgr101 = UPGR101_RECEIVED;
-
- /* we'll get more headers (HTTP/2 response) */
- k->header = TRUE;
- k->headerline = 0; /* restart the header line counter */
- switch_to_h2 = TRUE;
- }
-#ifdef USE_WEBSOCKETS
- else if(k->upgr101 == UPGR101_WS) {
- /* verify the response */
- result = Curl_ws_accept(data, buf, blen);
- if(result)
- return result;
- k->header = FALSE; /* no more header to parse! */
- *pconsumed += blen; /* ws accept handled the data */
- blen = 0;
- if(data->set.connect_only)
- k->keepon &= ~KEEP_RECV; /* read no more content */
- }
-#endif
- else {
- /* Not switching to another protocol */
- k->header = FALSE; /* no more header to parse! */
- }
- }
- else {
- /* invalid for other HTTP versions */
- failf(data, "unexpected 101 response code");
- return CURLE_WEIRD_SERVER_REPLY;
- }
- break;
- default:
- /* the status code 1xx indicates a provisional response, so
- we'll get another set of headers */
- k->header = TRUE;
- k->headerline = 0; /* restart the header line counter */
- break;
- }
- }
- else {
- if(k->upgr101 == UPGR101_H2) {
- /* A requested upgrade was denied, poke the multi handle to possibly
- allow a pending pipewait to continue */
- Curl_multi_connchanged(data->multi);
- }
- k->header = FALSE; /* no more header to parse! */
-
- if((k->size == -1) && !k->chunk && !conn->bits.close &&
- (conn->httpversion == 11) &&
- !(conn->handler->protocol & CURLPROTO_RTSP) &&
- data->state.httpreq != HTTPREQ_HEAD) {
- /* On HTTP 1.1, when connection is not to get closed, but no
- Content-Length nor Transfer-Encoding chunked have been
- received, according to RFC2616 section 4.4 point 5, we
- assume that the server will close the connection to
- signal the end of the document. */
- infof(data, "no chunk, no close, no size. Assume close to "
- "signal end");
- streamclose(conn, "HTTP: No end-of-message indicator");
- }
- }
-
- if(!k->header) {
- result = Curl_http_size(data);
- if(result)
- return result;
- }
-
- /* At this point we have some idea about the fate of the connection.
- If we are closing the connection it may result auth failure. */
-#if defined(USE_NTLM)
- if(conn->bits.close &&
- (((data->req.httpcode == 401) &&
- (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
- ((data->req.httpcode == 407) &&
- (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
- infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
- data->state.authproblem = TRUE;
- }
-#endif
-#if defined(USE_SPNEGO)
- if(conn->bits.close &&
- (((data->req.httpcode == 401) &&
- (conn->http_negotiate_state == GSS_AUTHRECV)) ||
- ((data->req.httpcode == 407) &&
- (conn->proxy_negotiate_state == GSS_AUTHRECV)))) {
- infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
- data->state.authproblem = TRUE;
- }
- if((conn->http_negotiate_state == GSS_AUTHDONE) &&
- (data->req.httpcode != 401)) {
- conn->http_negotiate_state = GSS_AUTHSUCC;
- }
- if((conn->proxy_negotiate_state == GSS_AUTHDONE) &&
- (data->req.httpcode != 407)) {
- conn->proxy_negotiate_state = GSS_AUTHSUCC;
- }
-#endif
+ /* Empty header line means end of headers! */
+ size_t consumed;
/* now, only output this if the header AND body are requested:
*/
+ Curl_debug(data, CURLINFO_HEADER_IN, hd, hdlen);
+
writetype = CLIENTWRITE_HEADER |
((k->httpcode/100 == 1) ? CLIENTWRITE_1XX : 0);
result = Curl_bump_headersize(data, hdlen, FALSE);
if(result)
return result;
-
- /*
- * When all the headers have been parsed, see if we should give
- * up and return an error.
- */
- if(http_should_fail(data)) {
- failf(data, "The requested URL returned error: %d",
- k->httpcode);
- return CURLE_HTTP_RETURNED_ERROR;
- }
-
-#ifdef USE_WEBSOCKETS
- /* All non-101 HTTP status codes are bad when wanting to upgrade to
- websockets */
- if(data->req.upgr101 == UPGR101_WS) {
- failf(data, "Refused WebSockets upgrade: %d", k->httpcode);
- return CURLE_HTTP_RETURNED_ERROR;
- }
-#endif
-
+ /* We are done with this line. We reset because response
+ * processing might switch to HTTP/2 and that might call us
+ * directly again. */
+ Curl_dyn_reset(&data->state.headerb);
data->req.deductheadercount =
(100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
- /* Curl_http_auth_act() checks what authentication methods
- * that are available and decides which one (if any) to
- * use. It will set 'newurl' if an auth method was picked. */
- result = Curl_http_auth_act(data);
-
+ /* analyze the response to find out what to do */
+ result = http_on_response(data, buf, blen, &consumed);
if(result)
return result;
+ *pconsumed += consumed;
+ blen -= consumed;
+ buf += consumed;
- if(k->httpcode >= 300) {
- if((!data->req.authneg) && !conn->bits.close &&
- !Curl_creader_will_rewind(data)) {
- /*
- * General treatment of errors when about to send data. Including :
- * "417 Expectation Failed", while waiting for 100-continue.
- *
- * The check for close above is done simply because of something
- * else has already deemed the connection to get closed then
- * something else should've considered the big picture and we
- * avoid this check.
- *
- * rewindbeforesend indicates that something has told libcurl to
- * continue sending even if it gets discarded
- */
-
- switch(data->state.httpreq) {
- case HTTPREQ_PUT:
- case HTTPREQ_POST:
- case HTTPREQ_POST_FORM:
- case HTTPREQ_POST_MIME:
- /* We got an error response. If this happened before the whole
- * request body has been sent we stop sending and mark the
- * connection for closure after we've read the entire response.
- */
- if(!Curl_req_done_sending(data)) {
- if((k->httpcode == 417) && Curl_http_exp100_is_selected(data)) {
- /* 417 Expectation Failed - try again without the Expect
- header */
- if(!k->writebytecount && http_exp100_is_waiting(data)) {
- infof(data, "Got HTTP failure 417 while waiting for a 100");
- }
- else {
- infof(data, "Got HTTP failure 417 while sending data");
- streamclose(conn,
- "Stop sending data before everything sent");
- result = http_perhapsrewind(data, conn);
- if(result)
- return result;
- }
- data->state.disableexpect = TRUE;
- DEBUGASSERT(!data->req.newurl);
- data->req.newurl = strdup(data->state.url);
- Curl_req_abort_sending(data);
- }
- else if(data->set.http_keep_sending_on_error) {
- infof(data, "HTTP error before end of send, keep sending");
- http_exp100_send_anyway(data);
- }
- else {
- infof(data, "HTTP error before end of send, stop sending");
- streamclose(conn, "Stop sending data before everything sent");
- result = Curl_req_abort_sending(data);
- if(result)
- return result;
- }
- }
- break;
-
- default: /* default label present to avoid compiler warnings */
- break;
- }
- }
-
- if(Curl_creader_will_rewind(data) && !Curl_req_done_sending(data)) {
- /* We rewind before next send, continue sending now */
- infof(data, "Keep sending data to get tossed away");
- k->keepon |= KEEP_SEND;
- }
- }
-
- if(!k->header) {
- /*
- * really end-of-headers.
- *
- * If we requested a "no body", this is a good time to get
- * out and return home.
- */
- if(data->req.no_body)
- k->download_done = TRUE;
-
- /* If max download size is *zero* (nothing) we already have
- nothing and can safely return ok now! But for HTTP/2, we'd
- like to call http2_handle_stream_close to properly close a
- stream. In order to do this, we keep reading until we
- close the stream. */
- if(0 == k->maxdownload
- && !Curl_conn_is_http2(data, conn, FIRSTSOCKET)
- && !Curl_conn_is_http3(data, conn, FIRSTSOCKET))
- k->download_done = TRUE;
-
- Curl_debug(data, CURLINFO_HEADER_IN,
- Curl_dyn_ptr(&data->state.headerb),
- Curl_dyn_len(&data->state.headerb));
+ if(!k->header || !blen)
goto out; /* exit header line loop */
- }
-
- /* We continue reading headers, reset the line-based header */
- Curl_dyn_reset(&data->state.headerb);
- if(switch_to_h2) {
- /* Having handled the headers, we can do the HTTP/2 switch.
- * Any remaining `buf` bytes are already HTTP/2 and passed to
- * be processed. */
- result = Curl_http2_upgrade(data, conn, FIRSTSOCKET, buf, blen);
- if(result)
- return result;
- *pconsumed += blen;
- blen = 0;
- }
continue;
}
/* This is the first header, it MUST be the error code line
or else we consider this to be the body right away! */
bool fine_statusline = FALSE;
+
+ k->httpversion = 0; /* Don't know yet */
if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
/*
* https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2
* says. We allow any three-digit number here, but we cannot make
* guarantees on future behaviors since it isn't within the protocol.
*/
- int httpversion = 0;
char *p = hd;
while(*p && ISBLANK(*p))
p++;
if((p[0] == '.') && (p[1] == '0' || p[1] == '1')) {
if(ISBLANK(p[2])) {
- httpversion = 10 + (p[1] - '0');
+ k->httpversion = 10 + (p[1] - '0');
p += 3;
if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
case '3':
if(!ISBLANK(p[1]))
break;
- httpversion = (*p - '0') * 10;
+ k->httpversion = (*p - '0') * 10;
p += 2;
if(ISDIGIT(p[0]) && ISDIGIT(p[1]) && ISDIGIT(p[2])) {
k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 +
}
}
- if(fine_statusline) {
- if(k->httpcode < 100) {
- failf(data, "Unsupported response code in HTTP response");
- return CURLE_UNSUPPORTED_PROTOCOL;
- }
- switch(httpversion) {
- case 10:
- case 11:
-#ifdef USE_HTTP2
- case 20:
-#endif
-#ifdef ENABLE_QUIC
- case 30:
-#endif
- conn->httpversion = (unsigned char)httpversion;
- break;
- default:
- failf(data, "Unsupported HTTP version (%u.%d) in response",
- httpversion/10, httpversion%10);
- return CURLE_UNSUPPORTED_PROTOCOL;
- }
-
- if(k->upgr101 == UPGR101_RECEIVED) {
- /* supposedly upgraded to http2 now */
- if(conn->httpversion != 20)
- infof(data, "Lying server, not serving HTTP/2");
- }
- if(conn->httpversion < 20) {
- conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
- }
- }
- else {
+ if(!fine_statusline) {
/* If user has set option HTTP200ALIASES,
compare header line against list of aliases
*/
- statusline check =
- checkhttpprefix(data,
- Curl_dyn_ptr(&data->state.headerb),
- Curl_dyn_len(&data->state.headerb));
+ statusline check = checkhttpprefix(data, hd, hdlen);
if(check == STATUS_DONE) {
fine_statusline = TRUE;
k->httpcode = 200;
- conn->httpversion = 10;
+ k->httpversion = 10;
}
}
}
p += 3;
if(ISSPACE(*p)) {
fine_statusline = TRUE;
- conn->httpversion = 11; /* RTSP acts like HTTP 1.1 */
+ k->httpversion = 11; /* RTSP acts like HTTP 1.1 */
}
}
}
return result;
/*
- * End of header-checks. Write them to the client.
+ * Taken in one (more) header. Write it to the client.
*/
- if(k->httpcode/100 == 1)
- writetype |= CLIENTWRITE_1XX;
-
Curl_debug(data, CURLINFO_HEADER_IN, hd, hdlen);
+ if(k->httpcode/100 == 1)
+ writetype |= CLIENTWRITE_1XX;
result = Curl_client_write(data, writetype, hd, hdlen);
if(result)
return result;