]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
http: prefer chunked encoding over Content-Length: 0
authorJosef Cejka <jcejka@suse.de>
Wed, 20 May 2026 16:07:16 +0000 (18:07 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 1 Jun 2026 21:40:28 +0000 (23:40 +0200)
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
tests/data/Makefile.am
tests/data/test1677 [new file with mode: 0644]

index 26f5280502f1e54b3da15ded2f59f02caf096086..e16d15a446ffef822df654a7604cfcd916117be4 100644 (file)
@@ -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 */
index 058be3d73488aa33d7aa9c238334b1f7688b5628..defe69c9175c2b2801792dd883efc1bd3c281a49 100644 (file)
@@ -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 (file)
index 0000000..dbf5ca1
--- /dev/null
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+chunked Transfer-Encoding
+Content-Length
+</keywords>
+</info>
+
+# 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
+<reply>
+<servercmd>
+writedelay: 500
+</servercmd>
+<data nocheck="yes" crlf="headers">
+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
+
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+HTTP POST response with both Transfer-Encoding chunked and Content-Length 0
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -d "testdata"
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol nonewline="yes" crlf="headers">
+POST /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Content-Length: 8
+Content-Type: application/x-www-form-urlencoded
+
+testdata
+</protocol>
+<stdout nonewline="yes" crlf="headers">
+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
+</stdout>
+</verify>
+</testcase>