mirror of
https://github.com/traefik/traefik.git
synced 2026-06-08 16:22:52 -04:00
Merge branch v2.11 into v3.6
This commit is contained in:
commit
15c47f9cb4
8 changed files with 122 additions and 52 deletions
|
|
@ -346,6 +346,9 @@ linters:
|
|||
text: 'appendAssign: append result not assigned to the same slice'
|
||||
linters:
|
||||
- gocritic
|
||||
- path: pkg/server/conncontext.go
|
||||
linters:
|
||||
- fatcontext
|
||||
paths:
|
||||
- pkg/provider/kubernetes/crd/generated/
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,11 @@
|
|||
## [v2.11.49](https://github.com/traefik/traefik/tree/v2.11.49) (2026-06-05)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.11.48...v2.11.49)
|
||||
|
||||
**Bug fixes:**
|
||||
- **[http3]** Bump github.com/quic-go/quic-go to v0.59.1 ([#13300](https://github.com/traefik/traefik/pull/13300) @rtribotte)
|
||||
- **[webui]** Bump axios to v1.17.0 ([#13299](https://github.com/traefik/traefik/pull/13299) @gndz07)
|
||||
- **[tls]** Fix snicheck with keepalive ([#13305](https://github.com/traefik/traefik/pull/13305) @juliens)
|
||||
|
||||
## [v3.6.19](https://github.com/traefik/traefik/tree/v3.6.19) (2026-06-04)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v3.6.17...v3.6.19)
|
||||
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -56,7 +56,7 @@ require (
|
|||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // No tag on the repo.
|
||||
github.com/prometheus/client_golang v1.23.0
|
||||
github.com/prometheus/client_model v0.6.2
|
||||
github.com/quic-go/quic-go v0.59.0
|
||||
github.com/quic-go/quic-go v0.59.1
|
||||
github.com/redis/go-redis/v9 v9.8.0
|
||||
github.com/rs/zerolog v1.33.0
|
||||
github.com/sirupsen/logrus v1.9.4
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -1819,8 +1819,8 @@ github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9
|
|||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||
github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
|
||||
github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||
github.com/quic-go/quic-go v0.59.1 h1:0Gmua0HW1Tv7ANR7hUYwRyD0MG5OJfgvYSZasGZzBic=
|
||||
github.com/quic-go/quic-go v0.59.1/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI=
|
||||
|
|
|
|||
29
pkg/server/conncontext.go
Normal file
29
pkg/server/conncontext.go
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
)
|
||||
|
||||
type connContextFunc func(context.Context, net.Conn) context.Context
|
||||
|
||||
type multipleConnContext struct {
|
||||
fns []connContextFunc
|
||||
}
|
||||
|
||||
func (m *multipleConnContext) AddConnContextFunc(fn connContextFunc) {
|
||||
m.fns = append(m.fns, fn)
|
||||
}
|
||||
|
||||
func (m *multipleConnContext) Build() connContextFunc {
|
||||
if len(m.fns) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return func(ctx context.Context, c net.Conn) context.Context {
|
||||
for _, contextFunc := range m.fns {
|
||||
ctx = contextFunc(ctx, c)
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
}
|
||||
26
pkg/server/conncontext_test.go
Normal file
26
pkg/server/conncontext_test.go
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type keyTest string
|
||||
|
||||
func TestConnContext(t *testing.T) {
|
||||
var connContext multipleConnContext
|
||||
connContext.AddConnContextFunc(func(ctx context.Context, _ net.Conn) context.Context {
|
||||
return context.WithValue(ctx, keyTest("test"), "test")
|
||||
})
|
||||
connContext.AddConnContextFunc(func(ctx context.Context, _ net.Conn) context.Context {
|
||||
return context.WithValue(ctx, keyTest("test2"), "test2")
|
||||
})
|
||||
|
||||
ctx := connContext.Build()(context.Background(), nil)
|
||||
|
||||
require.Equal(t, "test", ctx.Value(keyTest("test")))
|
||||
require.Equal(t, "test2", ctx.Value(keyTest("test2")))
|
||||
}
|
||||
|
|
@ -116,6 +116,13 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string
|
|||
logger := log.Ctx(ctx).With().Str(logs.RouterName, routerHTTPName).Logger()
|
||||
ctxRouter := logger.WithContext(provider.AddInContext(ctx, routerHTTPName))
|
||||
|
||||
// Even if the TLS options mismatch between the configured and the resolved one is handled in the aggregator
|
||||
// we also have to handle it here to be able to mark the router in error.
|
||||
tlsOptionsName := traefiktls.DefaultTLSConfigName
|
||||
if len(routerHTTPConfig.TLS.Options) > 0 && routerHTTPConfig.TLS.Options != traefiktls.DefaultTLSConfigName {
|
||||
tlsOptionsName = provider.GetQualifiedName(ctxRouter, routerHTTPConfig.TLS.Options)
|
||||
}
|
||||
|
||||
domains, err := httpmuxer.ParseDomains(routerHTTPConfig.Rule)
|
||||
if err != nil {
|
||||
routerErr := fmt.Errorf("invalid rule %s, error: %w", routerHTTPConfig.Rule, err)
|
||||
|
|
@ -155,17 +162,14 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string
|
|||
// # When a request for "/foo" comes, even though it won't be routed by httpRouter2,
|
||||
// # if its SNI is set to foo.com, myTLSOptions will be used for the TLS connection.
|
||||
// # Otherwise, it will fallback to the default TLS config.
|
||||
logger.Warn().Msgf("No domain found in rule %v, the TLS options applied for this router will depend on the SNI of each request", routerHTTPConfig.Rule)
|
||||
if tlsOptionsName != traefiktls.DefaultTLSConfigName {
|
||||
logger.Warn().Msgf("No domain found in rule %v, the TLS options applied for this router will depend on the SNI of each request", routerHTTPConfig.Rule)
|
||||
routerHTTPConfig.AddError(fmt.Errorf("no domain found in rule %v, the TLS option %s cannot be applied", routerHTTPConfig.Rule, tlsOptionsName), false)
|
||||
}
|
||||
}
|
||||
|
||||
// Even if the TLS options mismatch between the configured and the resolved one is handled in the aggregator
|
||||
// we also have to handle it here to be able to mark the router in error.
|
||||
tlsOptionsName := traefiktls.DefaultTLSConfigName
|
||||
if len(routerHTTPConfig.TLS.Options) > 0 && routerHTTPConfig.TLS.Options != traefiktls.DefaultTLSConfigName {
|
||||
tlsOptionsName = provider.GetQualifiedName(ctxRouter, routerHTTPConfig.TLS.Options)
|
||||
}
|
||||
|
||||
if routerHTTPConfig.TLS.ResolvedOptions != tlsOptionsName {
|
||||
if len(domains) > 0 && routerHTTPConfig.TLS.ResolvedOptions != tlsOptionsName {
|
||||
logger.Warn().Msg("Found different TLS options for routers on the same host, so using the default TLS options instead.")
|
||||
routerHTTPConfig.AddError(errors.New("found different TLS options for routers on the same host, so using the default TLS options instead"), false)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -677,6 +677,44 @@ func newHTTPServer(ctx context.Context, ln net.Listener, configuration *static.E
|
|||
|
||||
handler = denyFragment(handler)
|
||||
|
||||
var connContext multipleConnContext
|
||||
connContext.AddConnContextFunc(func(ctx context.Context, c net.Conn) context.Context {
|
||||
// This adds an empty struct in order to store a RoundTripper in the ConnContext in case of Kerberos or NTLM.
|
||||
ctx = service.AddTransportOnContext(ctx)
|
||||
|
||||
if tlsConn, ok := c.(*tls.Conn); ok {
|
||||
if tlsConnWithOptionsName, ok := tlsConn.NetConn().(tcp.TLSConn); ok {
|
||||
return tcp.AddTLSOptionsNameInContext(ctx, tlsConnWithOptionsName.TLSOptionsName)
|
||||
}
|
||||
}
|
||||
|
||||
return ctx
|
||||
})
|
||||
|
||||
if debugConnection || (configuration.Transport != nil && (configuration.Transport.KeepAliveMaxTime > 0 || configuration.Transport.KeepAliveMaxRequests > 0)) {
|
||||
connContext.AddConnContextFunc(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)
|
||||
})
|
||||
}
|
||||
|
||||
var connState func(c net.Conn, state http.ConnState)
|
||||
if debugConnection {
|
||||
connState = func(c net.Conn, state http.ConnState) {
|
||||
clientConnectionStatesMu.Lock()
|
||||
if clientConnectionStates[getConnKey(c)] != nil {
|
||||
clientConnectionStates[getConnKey(c)].State = state.String()
|
||||
}
|
||||
clientConnectionStatesMu.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
serverHTTP := &http.Server{
|
||||
Protocols: &protocols,
|
||||
Handler: handler,
|
||||
|
|
@ -690,46 +728,8 @@ func newHTTPServer(ctx context.Context, ln net.Listener, configuration *static.E
|
|||
MaxDecoderHeaderTableSize: int(configuration.HTTP2.MaxDecoderHeaderTableSize),
|
||||
MaxEncoderHeaderTableSize: int(configuration.HTTP2.MaxEncoderHeaderTableSize),
|
||||
},
|
||||
ConnContext: func(ctx context.Context, c net.Conn) context.Context {
|
||||
if tlsConn, ok := c.(*tls.Conn); ok {
|
||||
if tlsConnWithOptionsName, ok := tlsConn.NetConn().(tcp.TLSConn); ok {
|
||||
return tcp.AddTLSOptionsNameInContext(ctx, tlsConnWithOptionsName.TLSOptionsName)
|
||||
}
|
||||
}
|
||||
|
||||
return ctx
|
||||
},
|
||||
}
|
||||
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 {
|
||||
serverHTTP.ConnState = func(c net.Conn, state http.ConnState) {
|
||||
clientConnectionStatesMu.Lock()
|
||||
if clientConnectionStates[getConnKey(c)] != nil {
|
||||
clientConnectionStates[getConnKey(c)].State = state.String()
|
||||
}
|
||||
clientConnectionStatesMu.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prevConnContext := serverHTTP.ConnContext
|
||||
serverHTTP.ConnContext = func(ctx context.Context, c net.Conn) context.Context {
|
||||
// This adds an empty struct in order to store a RoundTripper in the ConnContext in case of Kerberos or NTLM.
|
||||
ctx = service.AddTransportOnContext(ctx)
|
||||
if prevConnContext != nil {
|
||||
return prevConnContext(ctx, c)
|
||||
}
|
||||
return ctx
|
||||
ConnContext: connContext.Build(),
|
||||
ConnState: connState,
|
||||
}
|
||||
|
||||
listener := newHTTPForwarder(ln)
|
||||
|
|
|
|||
Loading…
Reference in a new issue