From 23c7c78a1abf08ef2fc7aa60cfa7adc2c33e0d6e Mon Sep 17 00:00:00 2001
From: Romain <rtribotte@users.noreply.github.com>
Date: Tue, 27 May 2025 09:34:04 +0200
Subject: [PATCH] Add HTTP/2 maxConcurrentStream parameter test

---
 .../fixtures/https/max_concurrent_stream.toml | 28 ++++++++++++++
 integration/https_test.go                     | 37 +++++++++++++++++++
 2 files changed, 65 insertions(+)
 create mode 100644 integration/fixtures/https/max_concurrent_stream.toml

diff --git a/integration/fixtures/https/max_concurrent_stream.toml b/integration/fixtures/https/max_concurrent_stream.toml
new file mode 100644
index 000000000..912a47265
--- /dev/null
+++ b/integration/fixtures/https/max_concurrent_stream.toml
@@ -0,0 +1,28 @@
+[global]
+  checkNewVersion = false
+  sendAnonymousUsage = false
+
+[log]
+  level = "DEBUG"
+
+[serversTransport]
+  insecureSkipVerify=true
+
+[entryPoints]
+  [entryPoints.web]
+    address = ":8000"
+    [entryPoints.web.http2]
+      maxConcurrentStreams = 42
+
+[api]
+  insecure = true
+
+[providers.file]
+  filename = "{{ .SelfFilename }}"
+
+## dynamic configuration ##
+
+[tls.stores]
+  [tls.stores.default.defaultCertificate]
+    certFile = "resources/tls/local.cert"
+    keyFile = "resources/tls/local.key"
diff --git a/integration/https_test.go b/integration/https_test.go
index 9ced3ffb9..6e98e61d5 100644
--- a/integration/https_test.go
+++ b/integration/https_test.go
@@ -3,6 +3,7 @@ package integration
 import (
 	"bytes"
 	"crypto/tls"
+	"crypto/x509"
 	"fmt"
 	"net"
 	"net/http"
@@ -18,6 +19,7 @@ import (
 	"github.com/traefik/traefik/v2/integration/try"
 	"github.com/traefik/traefik/v2/pkg/config/dynamic"
 	traefiktls "github.com/traefik/traefik/v2/pkg/tls"
+	"golang.org/x/net/http2"
 )
 
 // HTTPSSuite tests suite.
@@ -1173,3 +1175,38 @@ func (s *HTTPSSuite) TestWithInvalidTLSOption() {
 		assert.Nil(s.T(), conn)
 	}
 }
+
+func (s *SimpleSuite) TestMaxConcurrentStream() {
+	file := s.adaptFile("fixtures/https/max_concurrent_stream.toml", struct{}{})
+
+	s.traefikCmd(withConfigFile(file), "--log.level=DEBUG", "--accesslog")
+
+	// Wait for traefik.
+	err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("api@internal"))
+	require.NoError(s.T(), err)
+
+	// Add client self-signed cert.
+	roots := x509.NewCertPool()
+	certContent, err := os.ReadFile("./resources/tls/local.cert")
+	require.NoError(s.T(), err)
+
+	roots.AppendCertsFromPEM(certContent)
+
+	// Open a connection to inspect SettingsFrame.
+	conn, err := tls.Dial("tcp", "127.0.0.1:8000", &tls.Config{
+		RootCAs:    roots,
+		NextProtos: []string{"h2"},
+	})
+	require.NoError(s.T(), err)
+
+	framer := http2.NewFramer(nil, conn)
+	frame, err := framer.ReadFrame()
+	require.NoError(s.T(), err)
+
+	fr, ok := frame.(*http2.SettingsFrame)
+	require.True(s.T(), ok)
+
+	maxConcurrentStream, ok := fr.Value(http2.SettingMaxConcurrentStreams)
+	assert.True(s.T(), ok)
+	assert.Equal(s.T(), uint32(42), maxConcurrentStream)
+}
-- 
GitLab