mirror of
https://github.com/traefik/traefik.git
synced 2025-05-05 23:43:01 +00:00
Apply keepalive config to h2c entrypoints
This commit is contained in:
parent
ef5f1b1508
commit
1c80f12bc2
@ -578,17 +578,17 @@ func createHTTPServer(ctx context.Context, ln net.Listener, configuration *stati
|
|||||||
handler = http.AllowQuerySemicolons(handler)
|
handler = http.AllowQuerySemicolons(handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debugConnection := os.Getenv(debugConnectionEnv) != ""
|
||||||
|
if debugConnection || (configuration.Transport != nil && (configuration.Transport.KeepAliveMaxTime > 0 || configuration.Transport.KeepAliveMaxRequests > 0)) {
|
||||||
|
handler = newKeepAliveMiddleware(handler, configuration.Transport.KeepAliveMaxRequests, configuration.Transport.KeepAliveMaxTime)
|
||||||
|
}
|
||||||
|
|
||||||
if withH2c {
|
if withH2c {
|
||||||
handler = h2c.NewHandler(handler, &http2.Server{
|
handler = h2c.NewHandler(handler, &http2.Server{
|
||||||
MaxConcurrentStreams: uint32(configuration.HTTP2.MaxConcurrentStreams),
|
MaxConcurrentStreams: uint32(configuration.HTTP2.MaxConcurrentStreams),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
debugConnection := os.Getenv(debugConnectionEnv) != ""
|
|
||||||
if debugConnection || (configuration.Transport != nil && (configuration.Transport.KeepAliveMaxTime > 0 || configuration.Transport.KeepAliveMaxRequests > 0)) {
|
|
||||||
handler = newKeepAliveMiddleware(handler, configuration.Transport.KeepAliveMaxRequests, configuration.Transport.KeepAliveMaxTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
serverHTTP := &http.Server{
|
serverHTTP := &http.Server{
|
||||||
Handler: handler,
|
Handler: handler,
|
||||||
ErrorLog: httpServerLogger,
|
ErrorLog: httpServerLogger,
|
||||||
|
@ -3,6 +3,7 @@ package server
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
@ -17,6 +18,7 @@ import (
|
|||||||
"github.com/traefik/traefik/v2/pkg/config/static"
|
"github.com/traefik/traefik/v2/pkg/config/static"
|
||||||
tcprouter "github.com/traefik/traefik/v2/pkg/server/router/tcp"
|
tcprouter "github.com/traefik/traefik/v2/pkg/server/router/tcp"
|
||||||
"github.com/traefik/traefik/v2/pkg/tcp"
|
"github.com/traefik/traefik/v2/pkg/tcp"
|
||||||
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestShutdownHijacked(t *testing.T) {
|
func TestShutdownHijacked(t *testing.T) {
|
||||||
@ -330,3 +332,53 @@ func TestKeepAliveMaxTime(t *testing.T) {
|
|||||||
err = resp.Body.Close()
|
err = resp.Body.Close()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestKeepAliveH2c(t *testing.T) {
|
||||||
|
epConfig := &static.EntryPointsTransport{}
|
||||||
|
epConfig.SetDefaults()
|
||||||
|
epConfig.KeepAliveMaxRequests = 1
|
||||||
|
|
||||||
|
entryPoint, err := NewTCPEntryPoint(context.Background(), &static.EntryPoint{
|
||||||
|
Address: ":0",
|
||||||
|
Transport: epConfig,
|
||||||
|
ForwardedHeaders: &static.ForwardedHeaders{},
|
||||||
|
HTTP2: &static.HTTP2Config{},
|
||||||
|
}, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
router, err := tcprouter.NewRouter()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
router.SetHTTPHandler(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
rw.WriteHeader(http.StatusOK)
|
||||||
|
}))
|
||||||
|
|
||||||
|
conn, err := startEntrypoint(entryPoint, router)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
http2Transport := &http2.Transport{
|
||||||
|
AllowHTTP: true,
|
||||||
|
DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
|
||||||
|
return conn, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &http.Client{Transport: http2Transport}
|
||||||
|
|
||||||
|
resp, err := client.Get("http://" + entryPoint.listener.Addr().String())
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.False(t, resp.Close)
|
||||||
|
err = resp.Body.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = client.Get("http://" + entryPoint.listener.Addr().String())
|
||||||
|
require.Error(t, err)
|
||||||
|
// Unlike HTTP/1, where we can directly check `resp.Close`, HTTP/2 uses a different
|
||||||
|
// mechanism: it sends a GOAWAY frame when the connection is closing.
|
||||||
|
// We can only check the error type. The error received should be poll.ErrClosed from
|
||||||
|
// the `internal/poll` package, but we cannot directly reference the error type due to
|
||||||
|
// package restrictions. Since this error message ("use of closed network connection")
|
||||||
|
// is distinct and specific, we rely on its consistency, assuming it is stable and unlikely
|
||||||
|
// to change.
|
||||||
|
require.Contains(t, err.Error(), "use of closed network connection")
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user