]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
http2: fix for http2-prior-knowledge when reusing connections
authorStefan Eissing <stefan@eissing.org>
Tue, 28 Feb 2023 10:43:50 +0000 (11:43 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 28 Feb 2023 22:04:00 +0000 (23:04 +0100)
- refs #10634 where errors in the HTTP/2 framing layer are observed.
- the bug was that on connection reuse, the code attempted to switch
  in yet another layer of HTTP/2 handling instead of detecting that
  this was already in place.
- added pytest testcase reproducing the issue.

Reported-by: rwmjones on github
Fixes #10634
Closes #10643

lib/http2.c
tests/tests-httpd/test_02_download.py
tests/tests-httpd/testenv/httpd.py

index bdb5e7378e9cbda72fc8ba1b94dc1f204892845e..f45b0ac5b1d0d17ff5a277b92a78c811ee98c17d 100644 (file)
@@ -2479,7 +2479,8 @@ bool Curl_http2_may_switch(struct Curl_easy *data,
                            int sockindex)
 {
   (void)sockindex;
-  if(data->state.httpwant == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
+  if(!Curl_conn_is_http2(data, conn, sockindex) &&
+     data->state.httpwant == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
 #ifndef CURL_DISABLE_PROXY
     if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
       /* We don't support HTTP/2 proxies yet. Also it's debatable
index 22cb260657cfde9de15dfcdcd88b973a3b22da41..680c9ea063083fb4b014f935c9262f6e3a5b8c6d 100644 (file)
@@ -221,6 +221,30 @@ class TestDownload:
         assert r.exit_code == 0
         r.check_stats(count=count, exp_status=200)
 
+    @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+    def test_02_12_head_serial_https(self, env: Env,
+                                     httpd, nghttpx, repeat, proto):
+        count = 100
+        urln = f'https://{env.authority_for(env.domain1, proto)}/data-10m?[0-{count-1}]'
+        curl = CurlClient(env=env)
+        r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[
+            '--head'
+        ])
+        assert r.exit_code == 0
+        r.check_stats(count=count, exp_status=200)
+
+    @pytest.mark.parametrize("proto", ['h2'])
+    def test_02_13_head_serial_h2c(self, env: Env,
+                                    httpd, nghttpx, repeat, proto):
+        count = 100
+        urln = f'http://{env.domain1}:{env.http_port}/data-10m?[0-{count-1}]'
+        curl = CurlClient(env=env)
+        r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[
+            '--head', '--http2-prior-knowledge', '--fail-early'
+        ])
+        assert r.exit_code == 0
+        r.check_stats(count=count, exp_status=200)
+
     def test_02_20_h2_small_frames(self, env: Env, httpd, repeat):
         # Test case to reproduce content corruption as observed in
         # https://github.com/curl/curl/issues/10525
index 4e027dfb54c5707054daf5e6cb18d1e066b3e95c..8b8859f9a21e2f921850dbdffd2f80261063bea1 100644 (file)
@@ -224,6 +224,7 @@ class Httpd:
                 f'LogLevel proxy_http:trace4',
                 f'H2MinWorkers 16',
                 f'H2MaxWorkers 128',
+                f'H2Direct on',
                 f'Listen {self.env.http_port}',
                 f'Listen {self.env.https_port}',
                 f'Listen {self.env.proxy_port}',
@@ -235,6 +236,7 @@ class Httpd:
                 f'    ServerName {domain1}',
                 f'    ServerAlias localhost',
                 f'    DocumentRoot "{self._docs_dir}"',
+                f'    Protocols h2c http/1.1',
             ])
             conf.extend(self._curltest_conf())
             conf.extend([