Apply keepalive config to h2c entrypoints
This commit is contained in:
parent
ef5f1b1508
commit
1c80f12bc2
2 changed files with 57 additions and 5 deletions
|
@ -578,17 +578,17 @@ func createHTTPServer(ctx context.Context, ln net.Listener, configuration *stati
|
|||
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 {
|
||||
handler = h2c.NewHandler(handler, &http2.Server{
|
||||
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{
|
||||
Handler: handler,
|
||||
ErrorLog: httpServerLogger,
|
||||
|
|
|
@ -3,6 +3,7 @@ package server
|
|||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
|
@ -17,6 +18,7 @@ import (
|
|||
"github.com/traefik/traefik/v2/pkg/config/static"
|
||||
tcprouter "github.com/traefik/traefik/v2/pkg/server/router/tcp"
|
||||
"github.com/traefik/traefik/v2/pkg/tcp"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
func TestShutdownHijacked(t *testing.T) {
|
||||
|
@ -330,3 +332,53 @@ func TestKeepAliveMaxTime(t *testing.T) {
|
|||
err = resp.Body.Close()
|
||||
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…
Reference in a new issue