Repository: traefik/traefik
File: pkg/server/server_entrypoint_tcp.go (Go)

Code before:

	var handler http.Handler
	handler, err = forwardedheaders.NewXForwarded(
		configuration.ForwardedHeaders.Insecure,
		configuration.ForwardedHeaders.TrustedIPs,
		next)
	if err != nil {
		return nil, err
	}

	handler = denyFragment(handler)
	if configuration.HTTP.EncodeQuerySemicolons {
		handler = encodeQuerySemicolons(handler)
	} else {
		handler = http.AllowQuerySemicolons(handler)
	}

	if withH2c {
		handler = h2c.NewHandler(handler, &http2.Server{
			MaxConcurrentStreams: uint32(configuration.HTTP2.MaxConcurrentStreams),
		})
	}

	var lastHandler http.Handler
	if debug || (configuration.Transport != nil && (configuration.Transport.KeepAliveMaxTime > 0 || configuration.Transport.KeepAliveMaxRequests > 0)) {
		lastHandler = http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
			state, ok := req.Context().Value(connStateKey).(*connState)
			if ok {
				state.IdleCycle++
				if configuration.Transport.KeepAliveMaxRequests > 0 && state.IdleCycle > configuration.Transport.KeepAliveMaxRequests {
					log.WithoutContext().Debug("Close because of too many requests")
					state.KeepAliveState = "Close because of too many requests"
					rw.Header().Set("Connection", "close")
				}
				if configuration.Transport.KeepAliveMaxTime > 0 && time.Now().After(state.Start.Add(time.Duration(configuration.Transport.KeepAliveMaxTime))) {
					log.WithoutContext().Debug("Close because of too long connection")
					state.KeepAliveState = "Close because of too long connection"
					rw.Header().Set("Connection", "close")
				}
			}
			handler.ServeHTTP(rw, req)
		})
	} else {
		lastHandler = handler
	}

	serverHTTP := &http.Server{
		Handler:      lastHandler,
		ErrorLog:     httpServerLogger,
		ReadTimeout:  time.Duration(configuration.Transport.RespondingTimeouts.ReadTimeout),
		WriteTimeout: time.Duration(configuration.Transport.RespondingTimeouts.WriteTimeout),

Review comment (suggestion):
Here I would do like above and have a dedicated unexposed function, to ease the readability (the function name is just an example) and have something like the following at the end:

```go
if configuration.Transport.KeepAliveMaxTime > 0 || configuration.Transport.KeepAliveMaxRequests > 0 {
handler = closeKeepAliveConnections(...)
}
```

Code after:
	next, err := alice.New(requestdecorator.WrapHandler(reqDecorator)).Then(httpSwitcher)
	if err != nil {
		return nil, err
	}

	var handler http.Handler
	handler, err = forwardedheaders.NewXForwarded(
		configuration.ForwardedHeaders.Insecure,
		configuration.ForwardedHeaders.TrustedIPs,
		next)
	if err != nil {
		return nil, err
	}

	handler = denyFragment(handler)
	if configuration.HTTP.EncodeQuerySemicolons {
		handler = encodeQuerySemicolons(handler)
	} else {
		handler = http.AllowQuerySemicolons(handler)
	}

	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,
		ReadTimeout:  time.Duration(configuration.Transport.RespondingTimeouts.ReadTimeout),
		WriteTimeout: time.Duration(configuration.Transport.RespondingTimeouts.WriteTimeout),
		IdleTimeout:  time.Duration(configuration.Transport.RespondingTimeouts.IdleTimeout),
	}
	if debugConnection || (configuration.Transport != nil && (configuration.Transport.KeepAliveMaxTime > 0 || configuration.Transport.KeepAliveMaxRequests > 0)) {
		serverHTTP.ConnContext = func(ctx context.Context, c net.Conn) context.Context {
			cState := &connState{Start: time.Now()}
			if debugConnection {
				clientConnectionStatesMu.Lock()
				clientConnectionStates[getConnKey(c)] = cState
				clientConnectionStatesMu.Unlock()
			}
			return context.WithValue(ctx, connStateKey, cState)
		}

		if debugConnection {