diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index c69535138..64d9493a8 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -10,7 +10,7 @@ on: - 'script/gcg/**' env: - GO_VERSION: '1.24' + GO_VERSION: '1.25' CGO_ENABLED: 0 jobs: diff --git a/.github/workflows/experimental.yaml b/.github/workflows/experimental.yaml index eda9d071b..78b5c24d9 100644 --- a/.github/workflows/experimental.yaml +++ b/.github/workflows/experimental.yaml @@ -7,7 +7,7 @@ on: - v* env: - GO_VERSION: '1.24' + GO_VERSION: '1.25' CGO_ENABLED: 0 jobs: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 5625be0c4..f29768640 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -6,7 +6,7 @@ on: - 'v*.*.*' env: - GO_VERSION: '1.24' + GO_VERSION: '1.25' CGO_ENABLED: 0 VERSION: ${{ github.ref_name }} TRAEFIKER_EMAIL: "traefiker@traefik.io" @@ -128,9 +128,9 @@ jobs: --exclude .idea \ --exclude .github \ --exclude dist . - + chown -R "$(id -u)":"$(id -g)" dist/ gh release create ${VERSION} ./dist/**/traefik*.{zip,tar.gz} ./dist/traefik*.{tar.gz,txt} --repo traefik/traefik --title ${VERSION} --notes ${VERSION} --latest=false - + ./script/deploy.sh diff --git a/.github/workflows/test-gateway-api-conformance.yaml b/.github/workflows/test-gateway-api-conformance.yaml index b0ef4b01a..13c361252 100644 --- a/.github/workflows/test-gateway-api-conformance.yaml +++ b/.github/workflows/test-gateway-api-conformance.yaml @@ -12,7 +12,7 @@ on: - 'integration/integration_test.go' env: - GO_VERSION: '1.24' + GO_VERSION: '1.25' CGO_ENABLED: 0 jobs: diff --git a/.github/workflows/test-integration.yaml b/.github/workflows/test-integration.yaml index 3cc982527..84bda71d9 100644 --- a/.github/workflows/test-integration.yaml +++ b/.github/workflows/test-integration.yaml @@ -10,7 +10,7 @@ on: - 'script/gcg/**' env: - GO_VERSION: '1.24' + GO_VERSION: '1.25' CGO_ENABLED: 0 jobs: diff --git a/.github/workflows/test-knative-conformance.yaml b/.github/workflows/test-knative-conformance.yaml index 54d41f72c..4ae0fbd2a 100644 --- a/.github/workflows/test-knative-conformance.yaml +++ b/.github/workflows/test-knative-conformance.yaml @@ -12,7 +12,7 @@ on: - 'integration/integration_test.go' env: - GO_VERSION: '1.24' + GO_VERSION: '1.25' CGO_ENABLED: 0 jobs: diff --git a/.github/workflows/test-unit.yaml b/.github/workflows/test-unit.yaml index f003bbea9..0b3a6247a 100644 --- a/.github/workflows/test-unit.yaml +++ b/.github/workflows/test-unit.yaml @@ -10,7 +10,7 @@ on: - 'script/gcg/**' env: - GO_VERSION: '1.24' + GO_VERSION: '1.25' jobs: generate-packages: diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml index d8898d8b5..397475a45 100644 --- a/.github/workflows/validate.yaml +++ b/.github/workflows/validate.yaml @@ -6,7 +6,7 @@ on: - '*' env: - GO_VERSION: '1.24' + GO_VERSION: '1.25' GOLANGCI_LINT_VERSION: v2.8.0 MISSPELL_VERSION: v0.7.0 diff --git a/go.mod b/go.mod index 79a1e9a94..44727336b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/traefik/traefik/v3 -go 1.24.0 +go 1.25.0 require ( github.com/BurntSushi/toml v1.6.0 @@ -215,7 +215,7 @@ require ( github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.21.2 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.1 // indirect @@ -391,7 +391,7 @@ require ( go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/arch v0.4.0 // indirect - golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect + golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect golang.org/x/oauth2 v0.34.0 // indirect golang.org/x/term v0.39.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 00b764cce..57d3e30a6 100644 --- a/go.sum +++ b/go.sum @@ -464,8 +464,9 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.21.2 h1:AqQaNADVwq/VnkCmQg6ogE+M3FOsKTytwges0JdwVuA= github.com/go-openapi/jsonpointer v0.21.2/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk= @@ -1524,8 +1525,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU= -golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= +golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM= +golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= diff --git a/pkg/healthcheck/healthcheck_tcp_test.go b/pkg/healthcheck/healthcheck_tcp_test.go index 4f80fd017..bb151cf93 100644 --- a/pkg/healthcheck/healthcheck_tcp_test.go +++ b/pkg/healthcheck/healthcheck_tcp_test.go @@ -571,12 +571,9 @@ func TestServiceTCPHealthChecker_differentIntervals(t *testing.T) { hc := NewServiceTCPHealthChecker(ctx, config, lb, serviceInfo, targets, "test-service") wg := sync.WaitGroup{} - wg.Add(1) - - go func() { + wg.Go(func() { hc.Launch(ctx) - wg.Done() - }() + }) // Let it run for 2 seconds to see the different check frequencies select { diff --git a/pkg/healthcheck/healthcheck_test.go b/pkg/healthcheck/healthcheck_test.go index 077a01349..cba259ce6 100644 --- a/pkg/healthcheck/healthcheck_test.go +++ b/pkg/healthcheck/healthcheck_test.go @@ -439,12 +439,9 @@ func TestServiceHealthChecker_Launch(t *testing.T) { hc := NewServiceHealthChecker(ctx, &MetricsMock{gauge}, config, lb, serviceInfo, http.DefaultTransport, map[string]*url.URL{"test": targetURL}, "foobar") wg := sync.WaitGroup{} - wg.Add(1) - - go func() { + wg.Go(func() { hc.Launch(ctx) - wg.Done() - }() + }) // Wait for expected health check events using channel synchronization. for i := range expectedEvents { @@ -508,12 +505,10 @@ func TestDifferentIntervals(t *testing.T) { hc := NewServiceHealthChecker(ctx, &MetricsMock{gauge}, config, lb, serviceInfo, http.DefaultTransport, map[string]*url.URL{"healthy": healthyURL, "unhealthy": unhealthyURL}, "foobar") wg := sync.WaitGroup{} - wg.Add(1) - - go func() { + wg.Go(func() { hc.Launch(ctx) wg.Done() - }() + }) select { case <-time.After(2 * time.Second): diff --git a/pkg/middlewares/accesslog/logger.go b/pkg/middlewares/accesslog/logger.go index 9ab1e6bd5..fd6c9a686 100644 --- a/pkg/middlewares/accesslog/logger.go +++ b/pkg/middlewares/accesslog/logger.go @@ -157,13 +157,11 @@ func NewHandler(ctx context.Context, config *otypes.AccessLog) (*Handler, error) } if config.BufferingSize > 0 { - logHandler.wg.Add(1) - go func() { - defer logHandler.wg.Done() + logHandler.wg.Go(func() { for handlerParams := range logHandler.logHandlerChan { logHandler.logTheRoundTrip(handlerParams.ctx, handlerParams.logDataTable) } - }() + }) } return logHandler, nil diff --git a/pkg/middlewares/forwardedheaders/forwarded_header.go b/pkg/middlewares/forwardedheaders/forwarded_header.go index 3f994b0a8..efc15e469 100644 --- a/pkg/middlewares/forwardedheaders/forwarded_header.go +++ b/pkg/middlewares/forwardedheaders/forwarded_header.go @@ -95,16 +95,14 @@ func isWebsocketRequest(req *http.Request) bool { containsHeader := func(name, value string) bool { h := unsafeHeader(req.Header).Get(name) for { - pos := strings.Index(h, ",") - if pos == -1 { - return strings.EqualFold(value, strings.TrimSpace(h)) - } - - if strings.EqualFold(value, strings.TrimSpace(h[:pos])) { + before, after, found := strings.Cut(h, ",") + if strings.EqualFold(value, strings.TrimSpace(before)) { return true } - - h = h[pos+1:] + if !found { + return false + } + h = after } } diff --git a/pkg/server/server_entrypoint_tcp.go b/pkg/server/server_entrypoint_tcp.go index 16d03bb84..34e4e5292 100644 --- a/pkg/server/server_entrypoint_tcp.go +++ b/pkg/server/server_entrypoint_tcp.go @@ -147,16 +147,12 @@ func (eps TCPEntryPoints) Stop() { var wg sync.WaitGroup for epn, ep := range eps { - wg.Add(1) - - go func(entryPointName string, entryPoint *TCPEntryPoint) { - defer wg.Done() - - logger := log.With().Str(logs.EntryPointName, entryPointName).Logger() - entryPoint.Shutdown(logger.WithContext(context.Background())) + wg.Go(func() { + logger := log.With().Str(logs.EntryPointName, epn).Logger() + ep.Shutdown(logger.WithContext(context.Background())) logger.Debug().Msg("Entrypoint closed") - }(epn, ep) + }) } wg.Wait() @@ -313,7 +309,6 @@ func (e *TCPEntryPoint) Shutdown(ctx context.Context) { var wg sync.WaitGroup shutdownServer := func(server stoppable) { - defer wg.Done() err := server.Shutdown(ctx) if err == nil { return @@ -334,24 +329,19 @@ func (e *TCPEntryPoint) Shutdown(ctx context.Context) { } if e.httpServer.Server != nil { - wg.Add(1) - go shutdownServer(e.httpServer.Server) + wg.Go(func() { shutdownServer(e.httpServer.Server) }) } if e.httpsServer.Server != nil { - wg.Add(1) - go shutdownServer(e.httpsServer.Server) + wg.Go(func() { shutdownServer(e.httpsServer.Server) }) if e.http3Server != nil { - wg.Add(1) - go shutdownServer(e.http3Server) + wg.Go(func() { shutdownServer(e.http3Server) }) } } if e.tracker != nil { - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := e.tracker.Shutdown(ctx) if err == nil { return @@ -360,7 +350,7 @@ func (e *TCPEntryPoint) Shutdown(ctx context.Context) { logger.Debug().Err(err).Msg("Server failed to shutdown before deadline") } e.tracker.Close() - }() + }) } wg.Wait() diff --git a/pkg/server/server_entrypoint_udp.go b/pkg/server/server_entrypoint_udp.go index 2d7250496..323d5ac2c 100644 --- a/pkg/server/server_entrypoint_udp.go +++ b/pkg/server/server_entrypoint_udp.go @@ -50,16 +50,14 @@ func (eps UDPEntryPoints) Stop() { var wg sync.WaitGroup for epn, ep := range eps { - wg.Add(1) - - go func(entryPointName string, entryPoint *UDPEntryPoint) { + wg.Go(func() { defer wg.Done() - logger := log.With().Str(logs.EntryPointName, entryPointName).Logger() - entryPoint.Shutdown(logger.WithContext(context.Background())) + logger := log.With().Str(logs.EntryPointName, epn).Logger() + ep.Shutdown(logger.WithContext(context.Background())) logger.Debug().Msg("Entry point closed") - }(epn, ep) + }) } wg.Wait() diff --git a/pkg/server/service/loadbalancer/leasttime/leasttime_test.go b/pkg/server/service/loadbalancer/leasttime/leasttime_test.go index 7c199eefc..ede621426 100644 --- a/pkg/server/service/loadbalancer/leasttime/leasttime_test.go +++ b/pkg/server/service/loadbalancer/leasttime/leasttime_test.go @@ -592,9 +592,7 @@ func TestConcurrentInflightTracking(t *testing.T) { numRequests := 50 for range numRequests { - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { handler.inflightCount.Add(1) defer handler.inflightCount.Add(-1) @@ -608,7 +606,7 @@ func TestConcurrentInflightTracking(t *testing.T) { } time.Sleep(1 * time.Millisecond) - }() + }) } wg.Wait() @@ -661,12 +659,10 @@ func TestConcurrentRequestsRespectInflight(t *testing.T) { inflightRequests := 5 for range inflightRequests { - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { recorder := httptest.NewRecorder() balancer.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/", nil)) - }() + }) } // Wait for goroutines to start and increment inflight counters. @@ -687,9 +683,7 @@ func TestConcurrentRequestsRespectInflight(t *testing.T) { // Launch new requests in background so they don't block. var newWg sync.WaitGroup for range newRequests { - newWg.Add(1) - go func() { - defer newWg.Done() + newWg.Go(func() { rec := httptest.NewRecorder() balancer.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/", nil)) server := rec.Header().Get("server") @@ -698,7 +692,7 @@ func TestConcurrentRequestsRespectInflight(t *testing.T) { save[server]++ saveMu.Unlock() } - }() + }) } // Wait for new requests to start and see the inflight counts.