http: split http_header into sub functions

Closes #17603
This commit is contained in:
Daniel Stenberg 2025-06-12 11:36:14 +02:00
parent c257753ee9
commit cbc062a7b8
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2

View File

@ -3001,20 +3001,14 @@ checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
Curl_compareheader(hd, STRCONST(n), STRCONST(v)))
/*
* http_header() parses a single response header.
* http_header_a() parses a single response header starting with A.
*/
static CURLcode http_header(struct Curl_easy *data,
static CURLcode http_header_a(struct Curl_easy *data,
const char *hd, size_t hdlen)
{
struct connectdata *conn = data->conn;
CURLcode result;
struct SingleRequest *k = &data->req;
const char *v;
switch(hd[0]) {
case 'a':
case 'A':
#ifndef CURL_DISABLE_ALTSVC
const char *v;
struct connectdata *conn = data->conn;
v = (data->asi &&
(Curl_conn_is_ssl(data->conn, FIRSTSOCKET) ||
#ifdef DEBUGBUILD
@ -3026,15 +3020,30 @@ static CURLcode http_header(struct Curl_easy *data,
)) ? HD_VAL(hd, hdlen, "Alt-Svc:") : NULL;
if(v) {
/* the ALPN of the current request */
struct SingleRequest *k = &data->req;
enum alpnid id = (k->httpversion == 30) ? ALPN_h3 :
(k->httpversion == 20) ? ALPN_h2 : ALPN_h1;
return Curl_altsvc_parse(data, data->asi, v, id, conn->host.name,
curlx_uitous((unsigned int)conn->remote_port));
}
#else
(void)data;
(void)hd;
(void)hdlen;
#endif
break;
case 'c':
case 'C':
return CURLE_OK;
}
/*
* http_header_c() parses a single response header starting with C.
*/
static CURLcode http_header_c(struct Curl_easy *data,
const char *hd, size_t hdlen)
{
struct connectdata *conn = data->conn;
struct SingleRequest *k = &data->req;
const char *v;
/* Check for Content-Length: header lines to get size */
v = (!k->http_bodyless && !data->set.ignorecl) ?
HD_VAL(hd, hdlen, "Content-Length:") : NULL;
@ -3140,10 +3149,18 @@ static CURLcode http_header(struct Curl_easy *data,
else if(k->httpcode < 300)
data->state.resume_from = 0; /* get everything */
}
break;
case 'l':
case 'L':
v = (!k->http_bodyless &&
return CURLE_OK;
}
/*
* http_header_l() parses a single response header starting with L.
*/
static CURLcode http_header_l(struct Curl_easy *data,
const char *hd, size_t hdlen)
{
struct connectdata *conn = data->conn;
struct SingleRequest *k = &data->req;
const char *v = (!k->http_bodyless &&
(data->set.timecondition || data->set.get_filetime)) ?
HD_VAL(hd, hdlen, "Last-Modified:") : NULL;
if(v) {
@ -3166,6 +3183,7 @@ static CURLcode http_header(struct Curl_easy *data,
data->req.location = location;
if(data->set.http_follow_mode) {
CURLcode result;
DEBUGASSERT(!data->req.newurl);
data->req.newurl = strdup(data->req.location); /* clone */
if(!data->req.newurl)
@ -3182,12 +3200,21 @@ static CURLcode http_header(struct Curl_easy *data,
}
}
}
break;
case 'p':
case 'P':
return CURLE_OK;
}
/*
* http_header_p() parses a single response header starting with P.
*/
static CURLcode http_header_p(struct Curl_easy *data,
const char *hd, size_t hdlen)
{
struct SingleRequest *k = &data->req;
#ifndef CURL_DISABLE_PROXY
v = HD_VAL(hd, hdlen, "Proxy-Connection:");
const char *v = HD_VAL(hd, hdlen, "Proxy-Connection:");
if(v) {
struct connectdata *conn = data->conn;
if((k->httpversion == 10) && conn->bits.httpproxy &&
HD_IS_AND_SAYS(hd, hdlen, "Proxy-Connection:", "keep-alive")) {
/*
@ -3213,6 +3240,7 @@ static CURLcode http_header(struct Curl_easy *data,
#endif
if((407 == k->httpcode) && HD_IS(hd, hdlen, "Proxy-authenticate:")) {
char *auth = Curl_copy_header_value(hd);
CURLcode result;
if(!auth)
return CURLE_OUT_OF_MEMORY;
result = Curl_http_input_auth(data, TRUE, auth);
@ -3221,6 +3249,7 @@ static CURLcode http_header(struct Curl_easy *data,
}
#ifdef USE_SPNEGO
if(HD_IS(hd, hdlen, "Persistent-Auth:")) {
struct connectdata *conn = data->conn;
struct negotiatedata *negdata = Curl_auth_nego_get(conn, FALSE);
struct auth *authp = &data->state.authhost;
if(!negdata)
@ -3237,10 +3266,16 @@ static CURLcode http_header(struct Curl_easy *data,
}
}
#endif
break;
case 'r':
case 'R':
v = HD_VAL(hd, hdlen, "Retry-After:");
return CURLE_OK;
}
/*
* http_header_r() parses a single response header starting with R.
*/
static CURLcode http_header_r(struct Curl_easy *data,
const char *hd, size_t hdlen)
{
const char *v = HD_VAL(hd, hdlen, "Retry-After:");
if(v) {
/* Retry-After = HTTP-date / delay-seconds */
curl_off_t retry_after = 0; /* zero for unknown or "now" */
@ -3265,11 +3300,19 @@ static CURLcode http_header(struct Curl_easy *data,
if(retry_after > 21600)
retry_after = 21600;
data->info.retry_after = retry_after;
}
return CURLE_OK;
}
break;
case 's':
case 'S':
/*
* http_header_s() parses a single response header starting with S.
*/
static CURLcode http_header_s(struct Curl_easy *data,
const char *hd, size_t hdlen)
{
struct connectdata *conn = data->conn;
const char *v;
#if !defined(CURL_DISABLE_COOKIES)
v = (data->cookies && data->state.cookie_engine) ?
HD_VAL(hd, hdlen, "Set-Cookie:") : NULL;
@ -3316,9 +3359,19 @@ static CURLcode http_header(struct Curl_easy *data,
#endif
}
#endif
break;
case 't':
case 'T':
return CURLE_OK;
}
/*
* http_header_t() parses a single response header starting with T.
*/
static CURLcode http_header_t(struct Curl_easy *data,
const char *hd, size_t hdlen)
{
struct connectdata *conn = data->conn;
struct SingleRequest *k = &data->req;
/* RFC 9112, ch. 6.1
* "Transfer-Encoding MAY be sent in a response to a HEAD request or
* in a 304 (Not Modified) response (Section 15.4.5 of [HTTP]) to a
@ -3329,14 +3382,14 @@ static CURLcode http_header(struct Curl_easy *data,
* Read: in these cases the 'Transfer-Encoding' does not apply
* to any data following the response headers. Do not add any decoders.
*/
v = (!k->http_bodyless &&
const char *v = (!k->http_bodyless &&
(data->state.httpreq != HTTPREQ_HEAD) &&
(k->httpcode != 304)) ?
HD_VAL(hd, hdlen, "Transfer-Encoding:") : NULL;
if(v) {
/* One or more encodings. We check for chunked and/or a compression
algorithm. */
result = Curl_build_unencoding_stack(data, v, TRUE);
CURLcode result = Curl_build_unencoding_stack(data, v, TRUE);
if(result)
return result;
if(!k->chunk && data->set.http_transfer_encoding) {
@ -3353,26 +3406,77 @@ static CURLcode http_header(struct Curl_easy *data,
data->req.resp_trailer = TRUE;
return CURLE_OK;
}
break;
case 'w':
case 'W':
return CURLE_OK;
}
/*
* http_header_w() parses a single response header starting with W.
*/
static CURLcode http_header_w(struct Curl_easy *data,
const char *hd, size_t hdlen)
{
struct SingleRequest *k = &data->req;
CURLcode result = CURLE_OK;
if((401 == k->httpcode) && HD_IS(hd, hdlen, "WWW-Authenticate:")) {
char *auth = Curl_copy_header_value(hd);
if(!auth)
return CURLE_OUT_OF_MEMORY;
result = Curl_http_input_auth(data, FALSE, auth);
free(auth);
}
return result;
}
/*
* http_header() parses a single response header.
*/
static CURLcode http_header(struct Curl_easy *data,
const char *hd, size_t hdlen)
{
CURLcode result = CURLE_OK;
switch(hd[0]) {
case 'a':
case 'A':
result = http_header_a(data, hd, hdlen);
break;
case 'c':
case 'C':
result = http_header_c(data, hd, hdlen);
break;
case 'l':
case 'L':
result = http_header_l(data, hd, hdlen);
break;
case 'p':
case 'P':
result = http_header_p(data, hd, hdlen);
break;
case 'r':
case 'R':
result = http_header_r(data, hd, hdlen);
break;
case 's':
case 'S':
result = http_header_s(data, hd, hdlen);
break;
case 't':
case 'T':
result = http_header_t(data, hd, hdlen);
break;
case 'w':
case 'W':
result = http_header_w(data, hd, hdlen);
break;
}
if(conn->handler->protocol & CURLPROTO_RTSP) {
if(!result) {
struct connectdata *conn = data->conn;
if(conn->handler->protocol & CURLPROTO_RTSP)
result = Curl_rtsp_parseheader(data, hd);
if(result)
return result;
}
return CURLE_OK;
return result;
}
/*