From ba600296d2a1d8a4e53a36eb4bd30c1f0d0152cc Mon Sep 17 00:00:00 2001 From: Josef Cejka Date: Wed, 20 May 2026 18:07:16 +0200 Subject: [PATCH] http: prefer chunked encoding over Content-Length: 0 Call http_size() before checking the request for empty body to prefer Transfer-Encoding: chunked even if Content-Length is 0. Closes #21706 --- lib/http.c | 19 ++++++----- tests/data/Makefile.am | 2 +- tests/data/test1677 | 77 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 tests/data/test1677 diff --git a/lib/http.c b/lib/http.c index 26f5280502..e16d15a446 100644 --- a/lib/http.c +++ b/lib/http.c @@ -4172,6 +4172,17 @@ static CURLcode http_on_response(struct Curl_easy *data, goto out; } + /* final response without error, prepare to receive the body */ + result = http_firstwrite(data); + if(result) + goto out; + + /* This is the last response that we get for the current request. Check on + * the body size and determine if the response is complete. */ + result = http_size(data); + if(result) + goto out; + /* If we requested a "no body", this is a good time to get * out and return home. */ @@ -4185,14 +4196,6 @@ static CURLcode http_on_response(struct Curl_easy *data, if((k->maxdownload == 0) && (k->httpversion_sent < 20)) k->download_done = TRUE; - /* final response without error, prepare to receive the body */ - result = http_firstwrite(data); - - if(!result) - /* This is the last response that we get for the current request. Check on - * the body size and determine if the response is complete. */ - result = http_size(data); - out: if(last_hd) /* if not written yet, write it now */ diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 058be3d734..defe69c917 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -222,7 +222,7 @@ test1650 test1651 test1652 test1653 test1654 test1655 test1656 test1657 \ test1658 test1659 test1660 test1661 test1662 test1663 test1664 test1665 \ test1666 test1667 test1668 test1669 \ \ -test1670 test1671 test1672 test1673 test1674 test1675 test1676 \ +test1670 test1671 test1672 test1673 test1674 test1675 test1676 test1677 \ \ test1680 test1681 test1682 test1683 test1684 test1685 \ \ diff --git a/tests/data/test1677 b/tests/data/test1677 new file mode 100644 index 0000000000..dbf5ca17a7 --- /dev/null +++ b/tests/data/test1677 @@ -0,0 +1,77 @@ + + + + +HTTP +HTTP POST +chunked Transfer-Encoding +Content-Length + + + +# Regression test for bug where curl stops reading chunked response +# when both Content-Length: 0 and Transfer-Encoding: chunked headers +# are present. Per RFC 7230 Section 3.3.3, Transfer-Encoding should +# take precedence and Content-Length should be ignored. +# The writedelay simulates the timing issue where chunks arrive in +# separate packets. + +# Server-side + + +writedelay: 500 + + +HTTP/1.1 200 OK +content-type: text/json +connection: keep-alive +content-length: 0 +transfer-encoding: chunked + +1a +random data in first chunk +1d + another data in second chunk +15 + third and last chunk +0 + + + + +# Client-side + + +http + + +HTTP POST response with both Transfer-Encoding chunked and Content-Length 0 + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER -d "testdata" + + + +# Verify data after the test has been "shot" + + +POST /%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +User-Agent: curl/%VERSION +Accept: */* +Content-Length: 8 +Content-Type: application/x-www-form-urlencoded + +testdata + + +HTTP/1.1 200 OK +content-type: text/json +connection: keep-alive +content-length: 0 +transfer-encoding: chunked + +random data in first chunk another data in second chunk third and last chunk + + +