diff --git a/lib/http.c b/lib/http.c index fbedeeebcf..ea62219542 100644 --- a/lib/http.c +++ b/lib/http.c @@ -4296,11 +4296,14 @@ static void unfold_header(struct Curl_easy *data) { size_t len = curlx_dyn_len(&data->state.headerb); char *hd = curlx_dyn_ptr(&data->state.headerb); - if(len && (hd[len -1] == '\n')) + if(len && (hd[len - 1] == '\n')) len--; - if(len && (hd[len -1] == '\r')) + if(len && (hd[len - 1] == '\r')) + len--; + while(len && (ISBLANK(hd[len - 1]))) /* strip off trailing whitespace */ len--; curlx_dyn_setlen(&data->state.headerb, len); + data->state.leading_unfold = TRUE; } /* @@ -4379,14 +4382,41 @@ static CURLcode http_parse_headers(struct Curl_easy *data, goto out; /* read more and try again */ } - /* decrease the size of the remaining (supposed) header line */ + /* the size of the remaining (supposed) header line */ consumed = (end_ptr - buf) + 1; - result = curlx_dyn_addn(&data->state.headerb, buf, consumed); - if(result) - return result; - blen -= consumed; - buf += consumed; - *pconsumed += consumed; + + { + /* preserve the whole original header piece size */ + size_t header_piece = consumed; + + if(data->state.leading_unfold) { + /* immediately after an unfold, keep only a single whitespace */ + const size_t iblen = blen; + while(consumed && ISBLANK(buf[0])) { + consumed--; + buf++; + blen--; + } + if(consumed) { + if(iblen > blen) { + /* take one step back */ + consumed++; + buf--; + blen++; + } + data->state.leading_unfold = FALSE; /* done now */ + } + } + + if(consumed) { + result = curlx_dyn_addn(&data->state.headerb, buf, consumed); + if(result) + return result; + blen -= consumed; + buf += consumed; + } + *pconsumed += header_piece; + } /**** * We now have a FULL header line in 'headerb'. diff --git a/lib/urldata.h b/lib/urldata.h index 062348233a..f3bdf37235 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1135,6 +1135,7 @@ struct UrlState { BIT(http_hd_upgrade); /* Added HTTP header Upgrade: */ BIT(http_hd_h2_settings); /* Added HTTP header H2Settings: */ BIT(maybe_folded); + BIT(leading_unfold); /* unfold started, this is the leading bytes */ #endif }; diff --git a/tests/data/test1274 b/tests/data/test1274 index 99d23ad8db..2f40b5d69d 100644 --- a/tests/data/test1274 +++ b/tests/data/test1274 @@ -55,7 +55,7 @@ Server: test-server/ fake folded Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT ETag: "21025-dc7-39462498" Content-Length: 6 -Connection:%repeat[46 x ]% close +Connection: close diff --git a/tests/data/test1940 b/tests/data/test1940 index 8f2f73437d..597adf851b 100644 --- a/tests/data/test1940 +++ b/tests/data/test1940 @@ -59,7 +59,7 @@ http://%HOSTIP:%HTTPPORT/%TESTNUMBER - Set-Cookie == onecookie=data; (0/3) - Set-Cookie == secondcookie=2data; (1/3) - Set-Cookie == cookie3=data3; (2/3) - Fold == is folding a line + Fold == is folding a line Blank ==%SP Blank2 ==%SP