]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
proxy: chunked response, error code
authorStefan Eissing <stefan@eissing.org>
Tue, 24 Mar 2026 09:03:18 +0000 (10:03 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 25 Mar 2026 11:16:21 +0000 (12:16 +0100)
Add test1715 to check proper handling of chunked transfer
encoding in CONNECT responses. Change proxy error code from
56 (RECV_ERROR) for everything to 7 (COULDNT_CONNECT) when
the server response could be read successfully, but establishing
the connection is not possible (http status code wrong).

Adapt several test expectations from 56 to 7.

Closes #21084

15 files changed:
lib/cf-h1-proxy.c
lib/cf-h2-proxy.c
tests/data/Makefile.am
tests/data/test1059
tests/data/test1715 [new file with mode: 0644]
tests/data/test217
tests/data/test287
tests/data/test302
tests/data/test440
tests/data/test441
tests/data/test493
tests/data/test718
tests/data/test749
tests/data/test94
tests/http/test_13_proxy_auth.py

index 36cb4eadb81e51c99d15c7fc01a63b8b9c6d3900..9e94e97e63b8a0c3ba66f0b95952ba4f17f3d74a 100644 (file)
@@ -465,17 +465,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
 
     if(ts->keepon == KEEPON_IGNORE) {
       /* This means we are currently ignoring a response-body */
-
-      if(ts->cl) {
-        /* A Content-Length based body: count down the counter
-           and make sure to break out of the loop when we are done! */
-        ts->cl--;
-        if(ts->cl <= 0) {
-          ts->keepon = KEEPON_DONE;
-          break;
-        }
-      }
-      else if(ts->chunked_encoding) {
+      if(ts->chunked_encoding) {
         /* chunked-encoded body, so we need to do the chunked dance
            properly to know when the end of the body is reached */
         size_t consumed = 0;
@@ -491,6 +481,15 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
           ts->keepon = KEEPON_DONE;
         }
       }
+      else if(ts->cl) {
+        /* A Content-Length based body: count down the counter
+           and make sure to break out of the loop when we are done! */
+        ts->cl--;
+        if(ts->cl <= 0) {
+          ts->keepon = KEEPON_DONE;
+          break;
+        }
+      }
       continue;
     }
 
@@ -597,6 +596,8 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
       /* read what is there */
       CURL_TRC_CF(data, cf, "CONNECT receive");
       result = recv_CONNECT_resp(cf, data, ts, &done);
+      if(result)
+        CURL_TRC_CF(data, cf, "error receiving CONNECT response: %d", result);
       if(!result)
         result = Curl_pgrsUpdate(data);
       /* error or not complete yet. return for more multi-multi */
@@ -645,7 +646,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
     Curl_safefree(data->req.newurl);
     h1_tunnel_go_state(cf, ts, H1_TUNNEL_FAILED, data);
     failf(data, "CONNECT tunnel failed, response %d", data->req.httpcode);
-    return CURLE_RECV_ERROR;
+    return CURLE_COULDNT_CONNECT;
   }
   /* 2xx response, SUCCESS! */
   h1_tunnel_go_state(cf, ts, H1_TUNNEL_ESTABLISHED, data);
index a9472b96c8aeb2d002e99fc6200e69bcbaa39e01..f836b05693e245a74375c231c39b89dcd4cd2439 100644 (file)
@@ -811,7 +811,7 @@ static CURLcode inspect_response(struct Curl_cfilter *cf,
   }
 
   /* Seems to have failed */
-  return CURLE_RECV_ERROR;
+  return CURLE_COULDNT_CONNECT;
 }
 
 static CURLcode H2_CONNECT(struct Curl_cfilter *cf,
index 3f410fe763c285658f4e0d398f87490220451179..f85d0b072326e0546fad20883b98c5ed521714f3 100644 (file)
@@ -229,7 +229,7 @@ test1670 test1671 test1672 test1673 \
 test1680 test1681 test1682 test1683 test1684 \
 \
 test1700 test1701 test1702 test1703 test1704 test1705 test1706 test1707 \
-test1708 test1709 test1710 test1711 test1712 test1713 test1714 \
+test1708 test1709 test1710 test1711 test1712 test1713 test1714 test1715 \
 \
 test1800 test1801 test1802 test1847 test1848 test1849 test1850 test1851 \
 \
index 63dbdf878f44a65d3e0995f94623a6816bb97894..c982ec3ac1a7096546f85c5c787b36d86700a25f 100644 (file)
@@ -42,7 +42,7 @@ ftp://test-number:%TESTNUMBER/wanted/page -p -x %HOSTIP:%HTTPPORT
 <verify>
 # The server does not implement CONNECT for ftp, so this must be a failure test
 <errorcode>
-56
+7
 </errorcode>
 <protocol crlf="headers">
 CONNECT test-number:%TESTNUMBER HTTP/1.1
diff --git a/tests/data/test1715 b/tests/data/test1715
new file mode 100644 (file)
index 0000000..df50322
--- /dev/null
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP CONNECT
+HTTP proxy
+proxytunnel
+</keywords>
+</info>
+
+<reply>
+
+<connect crlf="headers">
+HTTP/1.1 407 Proxy Authentication Required
+Proxy-Authenticate: Special realm="none", nonce="abc123"
+Content-Length: 13
+Transfer-Encoding: chunked
+Magic-special: true
+
+some content
+</connect>
+</reply>
+
+<client>
+<server>
+http
+</server>
+<features>
+proxy
+</features>
+<name>
+HTTP CONNECT with proxy returning Content-Length and chunked
+</name>
+<command>
+http://test.example --proxy http://%HOSTIP:%HTTPPORT --proxytunnel -sS
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="headers">
+CONNECT test.example:80 HTTP/1.1
+Host: test.example:80
+User-Agent: curl/%VERSION
+Proxy-Connection: Keep-Alive
+
+</protocol>
+<errorcode>
+56
+</errorcode>
+</verify>
+</testcase>
index eae1303d676d4f9b092e01c473aaaee358e710c8..a393700a05c312073a132142106678fb4f5efed9 100644 (file)
@@ -49,9 +49,9 @@ User-Agent: curl/%VERSION
 Proxy-Connection: Keep-Alive
 
 </protocol>
-# CURLE_RECV_ERROR
+# CURLE_COULDNT_CONNECT
 <errorcode>
-56
+7
 </errorcode>
 <stdout crlf="headers">
 HTTP/1.1 405 Method Not Allowed swsclose
index 00ae50bcb3df0545043c7bc28511b4c822d0be63..564b8ce99a1d8c6715f8d0887d0ec335f9f9db78 100644 (file)
@@ -45,9 +45,9 @@ Proxy-Connection: Keep-Alive
 User-Agent: looser/2007
 
 </protocol>
-# CURLE_RECV_ERROR
+# CURLE_COULDNT_CONNECT
 <errorcode>
-56
+7
 </errorcode>
 <stdout crlf="headers">
 HTTP/1.1 405 Method Not Allowed swsclose
index 5a68c1dd4b09e0e1f0acb866fbf1f7508f6db797..1bae0c76410f1bd98678c3995e0ad0dc74b2315c 100644 (file)
@@ -41,7 +41,7 @@ HTTPS GET over HTTP proxy fails
 # Verify data after the test has been "shot"
 <verify>
 <errorcode>
-56
+7
 </errorcode>
 <data>
 </data>
index ea4a0e224b19e878394d96dba579825e3559da27..3ed08f4730ddfca66aa0aa89ce317a3cbf4058bc 100644 (file)
@@ -72,7 +72,7 @@ https://this.hsts.example./%TESTNUMBER
 </stdout>
 # Proxy CONNECT aborted
 <errorcode>
-56
+7
 </errorcode>
 <limits>
 Allocations: 160
index 497ec7d7a13f2d0ec727f760ff511d3da7be2bdf..9574233302c78c236a9bc3c76cdb539ef8c47d11 100644 (file)
@@ -71,7 +71,7 @@ https://this.hsts.example/%TESTNUMBER
 </stdout>
 # Proxy CONNECT aborted
 <errorcode>
-56
+7
 </errorcode>
 </verify>
 </testcase>
index 1193dbd9711e04df84de241fa745a40c576fa52f..7c882c5600ef9fd7caa47459108050a45a0af9de 100644 (file)
@@ -70,7 +70,7 @@ https://this.hsts.example/%TESTNUMBER
 </stdout>
 # Proxy CONNECT aborted
 <errorcode>
-56
+7
 </errorcode>
 </verify>
 </testcase>
index f9a1a6d8de9e5839a44c78b247b8ab2204a4922b..0555c20d1947bb8e7943bdf0448264b3ea390689 100644 (file)
@@ -56,7 +56,7 @@ Proxy-Connection: Keep-Alive
 
 </protocol>
 <errorcode>
-56
+7
 </errorcode>
 </verify>
 </testcase>
index 86e15f8b5060418eaa70330f17d76439f3d91c4d..1a86e09fb3c0c1c892a12acac8c3b469312886dd 100644 (file)
@@ -53,10 +53,10 @@ Proxy-Connection: Keep-Alive
 
 </protocol>
 <errorcode>
-56
+7
 </errorcode>
 <stderr mode="text">
-curl: (56) CONNECT tunnel failed, response 400
+curl: (7) CONNECT tunnel failed, response 400
 </stderr>
 </verify>
 </testcase>
index 9824c745c1febc54dc315d88030fc760e3102dad..bca0a8e1cc71f1f9c8835b9e7f20b7de403200f2 100644 (file)
@@ -41,7 +41,7 @@ https://test.anything.really.com:%TESTNUMBER --proxy1.0 %HOSTIP:%HTTPPORT
 # Verify data after the test has been "shot"
 <verify>
 <errorcode>
-56
+7
 </errorcode>
 <protocol crlf="headers">
 CONNECT test.anything.really.com:%TESTNUMBER HTTP/1.0
index 33fb211e9973082c2e0b9acdb8b87ab7fd6dadce..0d7e744dca1ab1d75078f26ce68a4bdf6530f455 100644 (file)
@@ -104,7 +104,7 @@ class TestProxyAuth:
         r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
                                extra_args=xargs)
         # expect "COULD_NOT_CONNECT"
-        r.check_response(exitcode=56, http_status=None)
+        r.check_response(exitcode=7, http_status=None)
 
     def test_13_06_tunnel_http_auth(self, env: Env, httpd, configures_httpd):
         self.httpd_configure(env, httpd)
@@ -133,7 +133,7 @@ class TestProxyAuth:
         r = curl.http_download(urls=[url], alpn_proto=proto, with_stats=True,
                                extra_args=xargs)
         # expect "COULD_NOT_CONNECT"
-        r.check_response(exitcode=56, http_status=None)
+        r.check_response(exitcode=7, http_status=None)
         assert self.get_tunnel_proto_used(r) == tunnel
 
     @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")