mirror of
https://github.com/curl/curl.git
synced 2025-09-08 05:15:08 +03:00
parent
c257753ee9
commit
cbc062a7b8
184
lib/http.c
184
lib/http.c
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue
Block a user