From 4ff76e13c46f18894c2be72ad8b633001aedd582 Mon Sep 17 00:00:00 2001 From: Romain Date: Tue, 11 Mar 2025 15:32:04 +0100 Subject: [PATCH 01/18] Remove documentation for OriginStatusLine and DownstreamStatusLine accessLogs fields --- docs/content/observability/access-logs.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/content/observability/access-logs.md b/docs/content/observability/access-logs.md index 52e781319..fdac4550e 100644 --- a/docs/content/observability/access-logs.md +++ b/docs/content/observability/access-logs.md @@ -236,9 +236,7 @@ accessLog: | `OriginDuration` | The time taken (in nanoseconds) by the origin server ('upstream') to return its response. | | `OriginContentSize` | The content length specified by the origin server, or 0 if unspecified. | | `OriginStatus` | The HTTP status code returned by the origin server. If the request was handled by this Traefik instance (e.g. with a redirect), then this value will be absent (0). | - | `OriginStatusLine` | `OriginStatus` + Status code explanation | | `DownstreamStatus` | The HTTP status code returned to the client. | - | `DownstreamStatusLine` | `DownstreamStatus` + Status code explanation | | `DownstreamContentSize` | The number of bytes in the response entity returned to the client. This is in addition to the "Content-Length" header, which may be present in the origin response. | | `RequestCount` | The number of requests received since the Traefik instance started. | | `GzipRatio` | The response body compression ratio achieved. | From 5953331c7319601be30dda12c7cda59cb4b626d7 Mon Sep 17 00:00:00 2001 From: Kevin Pollet Date: Thu, 13 Mar 2025 09:42:04 +0100 Subject: [PATCH 02/18] Add back forwarded headers section in FAQ --- docs/content/getting-started/faq.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/content/getting-started/faq.md b/docs/content/getting-started/faq.md index 1c3d3f6a8..66f2d4d04 100644 --- a/docs/content/getting-started/faq.md +++ b/docs/content/getting-started/faq.md @@ -143,6 +143,21 @@ To take into account the new certificate contents, the update of the dynamic con One way to achieve that, is to trigger a file notification, for example, by using the `touch` command on the configuration file. +## What Are the Forwarded Headers When Proxying HTTP Requests? + +By default, the following headers are automatically added when proxying requests: + +| Property | HTTP Header | +|---------------------------|----------------------------| +| Client's IP | X-Forwarded-For, X-Real-Ip | +| Host | X-Forwarded-Host | +| Port | X-Forwarded-Port | +| Protocol | X-Forwarded-Proto | +| Proxy Server's Hostname | X-Forwarded-Server | + +For more details, +please check out the [forwarded header](../routing/entrypoints.md#forwarded-headers) documentation. + ## How Traefik is Storing and Serving TLS Certificates? ### Storing TLS Certificates From 55ebaee4a78edb4524f3324d1cb1a5740c4571f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9rald=20Cro=C3=ABs?= Date: Thu, 13 Mar 2025 09:44:04 +0100 Subject: [PATCH 03/18] Clarifies that retry middleware uses TCP, not HTTP status codes --- docs/content/middlewares/http/retry.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/content/middlewares/http/retry.md b/docs/content/middlewares/http/retry.md index 34b4ab695..9ec79c709 100644 --- a/docs/content/middlewares/http/retry.md +++ b/docs/content/middlewares/http/retry.md @@ -12,8 +12,11 @@ Retrying until it Succeeds TODO: add schema --> -The Retry middleware reissues requests a given number of times to a backend server if that server does not reply. -As soon as the server answers, the middleware stops retrying, regardless of the response status. +The Retry middleware reissues requests a given number of times when it cannot contact the backend service. +This applies at the transport level (TCP). +If the service does not respond to the initial connection attempt, the middleware retries. +However, once the service responds, regardless of the HTTP status code, the middleware considers it operational and stops retrying. +This means that the retry mechanism does not handle HTTP errors; it only retries when there is no response at the TCP level. The Retry middleware has an optional configuration to enable an exponential backoff. ## Configuration Examples From e76b65f44d7f050e67ce88bd33bd7ec0a938d8e2 Mon Sep 17 00:00:00 2001 From: nmengin Date: Thu, 13 Mar 2025 17:08:15 +0100 Subject: [PATCH 04/18] Add Security Support column in deprecation section --- docs/content/deprecation/releases.md | 43 ++++++++++++++++------------ 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/docs/content/deprecation/releases.md b/docs/content/deprecation/releases.md index d3fb7914b..d78604ec8 100644 --- a/docs/content/deprecation/releases.md +++ b/docs/content/deprecation/releases.md @@ -4,25 +4,30 @@ Below is a non-exhaustive list of versions and their maintenance status: -| Version | Release Date | Community Support | -|---------|--------------|--------------------| -| 3.3 | Jan 06, 2025 | Yes | -| 3.2 | Oct 28, 2024 | Ended Jan 06, 2025 | -| 3.1 | Jul 15, 2024 | Ended Oct 28, 2024 | -| 3.0 | Apr 29, 2024 | Ended Jul 15, 2024 | -| 2.11 | Feb 12, 2024 | Ends Apr 29, 2025 | -| 2.10 | Apr 24, 2023 | Ended Feb 12, 2024 | -| 2.9 | Oct 03, 2022 | Ended Apr 24, 2023 | -| 2.8 | Jun 29, 2022 | Ended Oct 03, 2022 | -| 2.7 | May 24, 2022 | Ended Jun 29, 2022 | -| 2.6 | Jan 24, 2022 | Ended May 24, 2022 | -| 2.5 | Aug 17, 2021 | Ended Jan 24, 2022 | -| 2.4 | Jan 19, 2021 | Ended Aug 17, 2021 | -| 2.3 | Sep 23, 2020 | Ended Jan 19, 2021 | -| 2.2 | Mar 25, 2020 | Ended Sep 23, 2020 | -| 2.1 | Dec 11, 2019 | Ended Mar 25, 2020 | -| 2.0 | Sep 16, 2019 | Ended Dec 11, 2019 | -| 1.7 | Sep 24, 2018 | Ended Dec 31, 2021 | +| Version | Release Date | Active Support | Security Support | +|---------|--------------|--------------------|------------------| +| 3.3 | Jan 06, 2025 | Yes | Yes | +| 3.2 | Oct 28, 2024 | Ended Jan 06, 2025 | No | +| 3.1 | Jul 15, 2024 | Ended Oct 28, 2024 | No | +| 3.0 | Apr 29, 2024 | Ended Jul 15, 2024 | No | +| 2.11 | Feb 12, 2024 | Ends Apr 29, 2025 | Ends Feb 01, 2026| +| 2.10 | Apr 24, 2023 | Ended Feb 12, 2024 | No | +| 2.9 | Oct 03, 2022 | Ended Apr 24, 2023 | No | +| 2.8 | Jun 29, 2022 | Ended Oct 03, 2022 | No | +| 2.7 | May 24, 2022 | Ended Jun 29, 2022 | No | +| 2.6 | Jan 24, 2022 | Ended May 24, 2022 | No | +| 2.5 | Aug 17, 2021 | Ended Jan 24, 2022 | No | +| 2.4 | Jan 19, 2021 | Ended Aug 17, 2021 | No | +| 2.3 | Sep 23, 2020 | Ended Jan 19, 2021 | No | +| 2.2 | Mar 25, 2020 | Ended Sep 23, 2020 | No | +| 2.1 | Dec 11, 2019 | Ended Mar 25, 2020 | No | +| 2.0 | Sep 16, 2019 | Ended Dec 11, 2019 | No | +| 1.7 | Sep 24, 2018 | Ended Dec 31, 2021 | No | + +??? example "Active Support / Security Support" + **Active support**: receives any bug fixes. + + **Security support**: receives only critical bug and security fixes. This page is maintained and updated periodically to reflect our roadmap and any decisions affecting the end of support for Traefik Proxy. From 137c6327938323dd1079d9c1d6a4d27bb40536c0 Mon Sep 17 00:00:00 2001 From: Nicolas Mengin Date: Fri, 14 Mar 2025 09:10:04 +0100 Subject: [PATCH 05/18] Add Security Support --- docs/content/deprecation/releases.md | 43 ++++++++++++++-------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/docs/content/deprecation/releases.md b/docs/content/deprecation/releases.md index d78604ec8..1a5fc0b03 100644 --- a/docs/content/deprecation/releases.md +++ b/docs/content/deprecation/releases.md @@ -4,30 +4,31 @@ Below is a non-exhaustive list of versions and their maintenance status: -| Version | Release Date | Active Support | Security Support | -|---------|--------------|--------------------|------------------| -| 3.3 | Jan 06, 2025 | Yes | Yes | -| 3.2 | Oct 28, 2024 | Ended Jan 06, 2025 | No | -| 3.1 | Jul 15, 2024 | Ended Oct 28, 2024 | No | -| 3.0 | Apr 29, 2024 | Ended Jul 15, 2024 | No | -| 2.11 | Feb 12, 2024 | Ends Apr 29, 2025 | Ends Feb 01, 2026| -| 2.10 | Apr 24, 2023 | Ended Feb 12, 2024 | No | -| 2.9 | Oct 03, 2022 | Ended Apr 24, 2023 | No | -| 2.8 | Jun 29, 2022 | Ended Oct 03, 2022 | No | -| 2.7 | May 24, 2022 | Ended Jun 29, 2022 | No | -| 2.6 | Jan 24, 2022 | Ended May 24, 2022 | No | -| 2.5 | Aug 17, 2021 | Ended Jan 24, 2022 | No | -| 2.4 | Jan 19, 2021 | Ended Aug 17, 2021 | No | -| 2.3 | Sep 23, 2020 | Ended Jan 19, 2021 | No | -| 2.2 | Mar 25, 2020 | Ended Sep 23, 2020 | No | -| 2.1 | Dec 11, 2019 | Ended Mar 25, 2020 | No | -| 2.0 | Sep 16, 2019 | Ended Dec 11, 2019 | No | -| 1.7 | Sep 24, 2018 | Ended Dec 31, 2021 | No | +| Version | Release Date | Active Support | Security Support | +|---------|--------------|--------------------|-------------------| +| 3.3 | Jan 06, 2025 | Yes | Yes | +| 3.2 | Oct 28, 2024 | Ended Jan 06, 2025 | No | +| 3.1 | Jul 15, 2024 | Ended Oct 28, 2024 | No | +| 3.0 | Apr 29, 2024 | Ended Jul 15, 2024 | No | +| 2.11 | Feb 12, 2024 | Ends Apr 29, 2025 | Ends Feb 01, 2026 | +| 2.10 | Apr 24, 2023 | Ended Feb 12, 2024 | No | +| 2.9 | Oct 03, 2022 | Ended Apr 24, 2023 | No | +| 2.8 | Jun 29, 2022 | Ended Oct 03, 2022 | No | +| 2.7 | May 24, 2022 | Ended Jun 29, 2022 | No | +| 2.6 | Jan 24, 2022 | Ended May 24, 2022 | No | +| 2.5 | Aug 17, 2021 | Ended Jan 24, 2022 | No | +| 2.4 | Jan 19, 2021 | Ended Aug 17, 2021 | No | +| 2.3 | Sep 23, 2020 | Ended Jan 19, 2021 | No | +| 2.2 | Mar 25, 2020 | Ended Sep 23, 2020 | No | +| 2.1 | Dec 11, 2019 | Ended Mar 25, 2020 | No | +| 2.0 | Sep 16, 2019 | Ended Dec 11, 2019 | No | +| 1.7 | Sep 24, 2018 | Ended Dec 31, 2021 | No | ??? example "Active Support / Security Support" - **Active support**: receives any bug fixes. - **Security support**: receives only critical bug and security fixes. + - **Active support**: Receives any bug fixes. + + - **Security support**: Receives only critical bug and security fixes. This page is maintained and updated periodically to reflect our roadmap and any decisions affecting the end of support for Traefik Proxy. From b02946147dec75b290645f801cdc8f7014f7f4b4 Mon Sep 17 00:00:00 2001 From: Kevin Pollet Date: Fri, 14 Mar 2025 09:24:05 +0100 Subject: [PATCH 06/18] Bump golang.org/x/net to v0.36.0 --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 67626418e..28f6052a2 100644 --- a/go.mod +++ b/go.mod @@ -74,8 +74,8 @@ require ( go.elastic.co/apm/module/apmot/v2 v2.4.8 go.elastic.co/apm/v2 v2.4.8 golang.org/x/mod v0.22.0 - golang.org/x/net v0.33.0 - golang.org/x/text v0.21.0 + golang.org/x/net v0.36.0 + golang.org/x/text v0.22.0 golang.org/x/time v0.8.0 golang.org/x/tools v0.28.0 google.golang.org/grpc v1.67.1 @@ -347,12 +347,12 @@ require ( go.uber.org/zap v1.21.0 // indirect go4.org/intern v0.0.0-20230525184215-6c62f75575cb // indirect go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 // indirect - golang.org/x/crypto v0.32.0 // indirect + golang.org/x/crypto v0.35.0 // indirect golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect golang.org/x/oauth2 v0.24.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.29.0 // indirect - golang.org/x/term v0.28.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/term v0.29.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/api v0.214.0 // indirect google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect diff --git a/go.sum b/go.sum index 29407ea7f..4d63beeaa 100644 --- a/go.sum +++ b/go.sum @@ -1489,8 +1489,8 @@ golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIi golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1601,8 +1601,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA= +golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1631,8 +1631,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1738,8 +1738,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1752,8 +1752,8 @@ golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= -golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= +golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1771,8 +1771,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 8ba99adc503b637b0e424605e2397ee132ddda34 Mon Sep 17 00:00:00 2001 From: Romain Date: Fri, 21 Mar 2025 11:00:06 +0100 Subject: [PATCH 07/18] Error level log for configuration-related TLS errors with backends Co-authored-by: Kevin Pollet --- pkg/server/service/proxy.go | 28 +++++++++++++++++-- pkg/server/service/proxy_test.go | 46 ++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/pkg/server/service/proxy.go b/pkg/server/service/proxy.go index 8f3c0a418..ca5f4150f 100644 --- a/pkg/server/service/proxy.go +++ b/pkg/server/service/proxy.go @@ -2,6 +2,7 @@ package service import ( "context" + "crypto/tls" "errors" "fmt" "io" @@ -91,8 +92,9 @@ func buildProxy(passHostHeader *bool, responseForwarding *dynamic.ResponseForwar BufferPool: bufferPool, ErrorLog: errorLogger, ErrorHandler: func(w http.ResponseWriter, request *http.Request, err error) { - statusCode := http.StatusInternalServerError + logger := log.FromContext(request.Context()) + statusCode := http.StatusInternalServerError switch { case errors.Is(err, io.EOF): statusCode = http.StatusBadGateway @@ -109,7 +111,13 @@ func buildProxy(passHostHeader *bool, responseForwarding *dynamic.ResponseForwar } } - log.Debugf("'%d %s' caused by: %v", statusCode, statusText(statusCode), err) + // Log the error with error level if it is a TLS error related to configuration. + if isTLSConfigError(err) { + logger.Errorf("'%d %s' caused by: %v", statusCode, statusText(statusCode), err) + } else { + logger.Debugf("'%d %s' caused by: %v", statusCode, statusText(statusCode), err) + } + w.WriteHeader(statusCode) _, werr := w.Write([]byte(statusText(statusCode))) if werr != nil { @@ -121,6 +129,22 @@ func buildProxy(passHostHeader *bool, responseForwarding *dynamic.ResponseForwar return proxy, nil } +// isTLSError returns true if the error is a TLS error which is related to configuration. +// We assume that if the error is a tls.RecordHeaderError or a tls.CertificateVerificationError, +// it is related to configuration, because the client should not send a TLS request to a non-TLS server, +// and the client configuration should allow to verify the server certificate. +func isTLSConfigError(err error) bool { + // tls.RecordHeaderError is returned when the client sends a TLS request to a non-TLS server. + var recordHeaderErr tls.RecordHeaderError + if errors.As(err, &recordHeaderErr) { + return true + } + + // tls.CertificateVerificationError is returned when the server certificate cannot be verified. + var certVerificationErr *tls.CertificateVerificationError + return errors.As(err, &certVerificationErr) +} + func isWebSocketUpgrade(req *http.Request) bool { if !httpguts.HeaderValuesContainsToken(req.Header["Connection"], "Upgrade") { return false diff --git a/pkg/server/service/proxy_test.go b/pkg/server/service/proxy_test.go index 40ca69d67..cae812380 100644 --- a/pkg/server/service/proxy_test.go +++ b/pkg/server/service/proxy_test.go @@ -1,12 +1,15 @@ package service import ( + "crypto/tls" + "errors" "io" "net/http" "net/http/httptest" "strings" "testing" + "github.com/stretchr/testify/require" "github.com/traefik/traefik/v2/pkg/testhelpers" ) @@ -35,3 +38,46 @@ func BenchmarkProxy(b *testing.B) { handler.ServeHTTP(w, req) } } + +func TestIsTLSConfigError(t *testing.T) { + testCases := []struct { + desc string + err error + expected bool + }{ + { + desc: "nil", + }, + { + desc: "TLS ECHRejectionError", + err: &tls.ECHRejectionError{}, + }, + { + desc: "TLS AlertError", + err: tls.AlertError(0), + }, + { + desc: "Random error", + err: errors.New("random error"), + }, + { + desc: "TLS RecordHeaderError", + err: tls.RecordHeaderError{}, + expected: true, + }, + { + desc: "TLS CertificateVerificationError", + err: &tls.CertificateVerificationError{}, + expected: true, + }, + } + + for _, test := range testCases { + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + actual := isTLSConfigError(test.err) + require.Equal(t, test.expected, actual) + }) + } +} From 08b90ade9419d221729e706330f1c7a1278f60e3 Mon Sep 17 00:00:00 2001 From: Kevin Pollet Date: Wed, 26 Mar 2025 09:30:05 +0100 Subject: [PATCH 08/18] Bump github.com/golang-jwt/jwt to v4.5.2 and v5.2.2 --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 28f6052a2..a1437a291 100644 --- a/go.mod +++ b/go.mod @@ -192,8 +192,8 @@ require ( github.com/goccy/go-json v0.10.4 // indirect github.com/gofrs/flock v0.12.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.1 // indirect - github.com/golang-jwt/jwt/v5 v5.2.1 // indirect + github.com/golang-jwt/jwt/v4 v4.5.2 // indirect + github.com/golang-jwt/jwt/v5 v5.2.2 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-querystring v1.1.0 // indirect diff --git a/go.sum b/go.sum index 4d63beeaa..d1579f31c 100644 --- a/go.sum +++ b/go.sum @@ -514,10 +514,10 @@ github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzq github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= -github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= -github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= +github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= +github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= From 54a2d657f354cb2f0aa118fbc808de43dd9857d5 Mon Sep 17 00:00:00 2001 From: Kevin Pollet Date: Wed, 26 Mar 2025 09:48:05 +0100 Subject: [PATCH 09/18] Bump github.com/redis/go-redis/v9 to v9.6.3 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a1437a291..89b61c8bb 100644 --- a/go.mod +++ b/go.mod @@ -288,7 +288,7 @@ require ( github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/quic-go/qpack v0.5.1 // indirect - github.com/redis/go-redis/v9 v9.6.1 // indirect + github.com/redis/go-redis/v9 v9.6.3 // indirect github.com/regfish/regfish-dnsapi-go v0.1.1 // indirect github.com/sacloud/api-client-go v0.2.10 // indirect github.com/sacloud/go-http v0.1.8 // indirect diff --git a/go.sum b/go.sum index d1579f31c..8a9315b5d 100644 --- a/go.sum +++ b/go.sum @@ -1162,8 +1162,8 @@ github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac/go.mod 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 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= -github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= +github.com/redis/go-redis/v9 v9.6.3 h1:8Dr5ygF1QFXRxIH/m3Xg9MMG1rS8YCtAgosrsewT6i0= +github.com/redis/go-redis/v9 v9.6.3/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= github.com/regfish/regfish-dnsapi-go v0.1.1 h1:TJFtbePHkd47q5GZwYl1h3DIYXmoxdLjW/SBsPtB5IE= github.com/regfish/regfish-dnsapi-go v0.1.1/go.mod h1:ubIgXSfqarSnl3XHSn8hIFwFF3h0yrq0ZiWD93Y2VjY= github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052 h1:Qp27Idfgi6ACvFQat5+VJvlYToylpM/hcyLBI3WaKPA= From 84742275a4a00ef517944dd3265ab6140649a355 Mon Sep 17 00:00:00 2001 From: Kevin Pollet Date: Wed, 26 Mar 2025 10:06:05 +0100 Subject: [PATCH 10/18] Bump golang.org/x/net to v0.37.0 --- cmd/traefik/traefik.go | 1 - go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ init/init.go | 21 --------------------- 4 files changed, 18 insertions(+), 40 deletions(-) delete mode 100644 init/init.go diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index 01dbb9ed2..9d3c7c953 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -23,7 +23,6 @@ import ( "github.com/traefik/traefik/v2/cmd" "github.com/traefik/traefik/v2/cmd/healthcheck" cmdVersion "github.com/traefik/traefik/v2/cmd/version" - _ "github.com/traefik/traefik/v2/init" tcli "github.com/traefik/traefik/v2/pkg/cli" "github.com/traefik/traefik/v2/pkg/collector" "github.com/traefik/traefik/v2/pkg/config/dynamic" diff --git a/go.mod b/go.mod index 89b61c8bb..989743fd7 100644 --- a/go.mod +++ b/go.mod @@ -74,8 +74,8 @@ require ( go.elastic.co/apm/module/apmot/v2 v2.4.8 go.elastic.co/apm/v2 v2.4.8 golang.org/x/mod v0.22.0 - golang.org/x/net v0.36.0 - golang.org/x/text v0.22.0 + golang.org/x/net v0.37.0 + golang.org/x/text v0.23.0 golang.org/x/time v0.8.0 golang.org/x/tools v0.28.0 google.golang.org/grpc v1.67.1 @@ -347,12 +347,12 @@ require ( go.uber.org/zap v1.21.0 // indirect go4.org/intern v0.0.0-20230525184215-6c62f75575cb // indirect go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 // indirect - golang.org/x/crypto v0.35.0 // indirect + golang.org/x/crypto v0.36.0 // indirect golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect golang.org/x/oauth2 v0.24.0 // indirect - golang.org/x/sync v0.11.0 // indirect - golang.org/x/sys v0.30.0 // indirect - golang.org/x/term v0.29.0 // indirect + golang.org/x/sync v0.12.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/term v0.30.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/api v0.214.0 // indirect google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect diff --git a/go.sum b/go.sum index 8a9315b5d..8ab908195 100644 --- a/go.sum +++ b/go.sum @@ -1489,8 +1489,8 @@ golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIi golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= -golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1601,8 +1601,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA= -golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1631,8 +1631,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= -golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1738,8 +1738,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1752,8 +1752,8 @@ golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= -golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= +golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= +golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1771,8 +1771,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/init/init.go b/init/init.go deleted file mode 100644 index e54655d0f..000000000 --- a/init/init.go +++ /dev/null @@ -1,21 +0,0 @@ -package init - -import ( - "os" - "strings" -) - -// This makes use of the GODEBUG flag `http2xconnect` to deactivate the connect setting for HTTP2 by default. -// This type of upgrade is yet incompatible with `net/http` http1 reverse proxy. -// Please see https://github.com/golang/go/issues/71128#issuecomment-2574193636. -func init() { - goDebug := os.Getenv("GODEBUG") - if strings.Contains(goDebug, "http2xconnect") { - return - } - - if len(goDebug) > 0 { - goDebug += "," - } - os.Setenv("GODEBUG", goDebug+"http2xconnect=0") -} From a5d46fc6ef11dcefb4d9aced0ca9379f5b7b1a04 Mon Sep 17 00:00:00 2001 From: Romain Date: Wed, 26 Mar 2025 10:22:05 +0100 Subject: [PATCH 11/18] Change boolean module properties default value to undefined --- webui/src/components/_commons/Chips.vue | 2 +- webui/src/components/_commons/PanelHealthCheck.vue | 2 +- webui/src/components/_commons/PanelMiddlewares.vue | 2 +- webui/src/components/_commons/PanelMirroringServices.vue | 2 +- webui/src/components/_commons/PanelServers.vue | 4 ++-- webui/src/components/_commons/PanelServiceDetails.vue | 2 +- webui/src/components/_commons/PanelWeightedServices.vue | 2 +- webui/src/components/_commons/StickyServiceDetails.vue | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/webui/src/components/_commons/Chips.vue b/webui/src/components/_commons/Chips.vue index 4108f6d27..531723a22 100644 --- a/webui/src/components/_commons/Chips.vue +++ b/webui/src/components/_commons/Chips.vue @@ -14,7 +14,7 @@ From 42778d2ba65520c4b7a4fe12e7acceac1c9a8415 Mon Sep 17 00:00:00 2001 From: Kevin Pollet Date: Wed, 26 Mar 2025 11:30:05 +0100 Subject: [PATCH 12/18] Do not abort request when response content-type is malformed --- pkg/middlewares/compress/compression_handler.go | 6 +++++- pkg/middlewares/compress/compression_handler_test.go | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/pkg/middlewares/compress/compression_handler.go b/pkg/middlewares/compress/compression_handler.go index 215607ccd..07583028b 100644 --- a/pkg/middlewares/compress/compression_handler.go +++ b/pkg/middlewares/compress/compression_handler.go @@ -233,8 +233,12 @@ func (r *responseWriter) Write(p []byte) (int, error) { // Disable compression according to user wishes in excludedContentTypes or includedContentTypes. if ct := r.rw.Header().Get(contentType); ct != "" { mediaType, params, err := mime.ParseMediaType(ct) + // To align the behavior with the klauspost handler for Gzip, + // if the MIME type is not parsable the compression is disabled. if err != nil { - return 0, fmt.Errorf("parsing content-type media type: %w", err) + r.compressionDisabled = true + r.rw.WriteHeader(r.statusCode) + return r.rw.Write(p) } if len(r.includedContentTypes) > 0 { diff --git a/pkg/middlewares/compress/compression_handler_test.go b/pkg/middlewares/compress/compression_handler_test.go index b078ed71f..89bbe062b 100644 --- a/pkg/middlewares/compress/compression_handler_test.go +++ b/pkg/middlewares/compress/compression_handler_test.go @@ -577,6 +577,11 @@ func Test_ExcludedContentTypes(t *testing.T) { contentType: "", expCompression: true, }, + { + desc: "MIME malformed", + contentType: "application/json;charset=UTF-8;charset=utf-8", + expCompression: false, + }, { desc: "MIME match", contentType: "application/json", @@ -687,6 +692,11 @@ func Test_IncludedContentTypes(t *testing.T) { contentType: "", expCompression: true, }, + { + desc: "MIME malformed", + contentType: "application/json;charset=UTF-8;charset=utf-8", + expCompression: false, + }, { desc: "MIME match", contentType: "application/json", From 2087e11f5528fb05a68943d2c40ebaf7444427a8 Mon Sep 17 00:00:00 2001 From: Kevin Pollet Date: Wed, 26 Mar 2025 17:52:05 +0100 Subject: [PATCH 13/18] Bump nokogiri to 1.18.6 and html-proofer to 5.0.10 --- docs/check.Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/check.Dockerfile b/docs/check.Dockerfile index 015e6f595..41a389f69 100644 --- a/docs/check.Dockerfile +++ b/docs/check.Dockerfile @@ -14,8 +14,8 @@ RUN apk --no-cache --no-progress add \ ruby-json \ zlib-dev -RUN gem install nokogiri --version 1.16.8 --no-document -- --use-system-libraries -RUN gem install html-proofer --version 5.0.7 --no-document -- --use-system-libraries +RUN gem install nokogiri --version 1.18.6 --no-document -- --use-system-libraries +RUN gem install html-proofer --version 5.0.10 --no-document -- --use-system-libraries # After Ruby, some NodeJS YAY! RUN apk --no-cache --no-progress add \ From 496f00c7c2c315b070b45d171ad4095656565f92 Mon Sep 17 00:00:00 2001 From: Romain Date: Fri, 28 Mar 2025 11:30:05 +0100 Subject: [PATCH 14/18] Revert compress middleware algorithms priority to v2 behavior Co-authored-by: Kevin Pollet --- docs/content/middlewares/http/compress.md | 4 +- docs/content/migration/v3.md | 10 ++ pkg/config/dynamic/middlewares.go | 2 +- pkg/middlewares/compress/acceptencoding.go | 84 +++++++---------- .../compress/acceptencoding_test.go | 91 +++++++++++++++---- pkg/middlewares/compress/compress.go | 34 +++++-- pkg/middlewares/compress/compress_test.go | 40 +++++++- 7 files changed, 181 insertions(+), 84 deletions(-) diff --git a/docs/content/middlewares/http/compress.md b/docs/content/middlewares/http/compress.md index 1f204be29..58d06de96 100644 --- a/docs/content/middlewares/http/compress.md +++ b/docs/content/middlewares/http/compress.md @@ -264,10 +264,10 @@ http: ### `encodings` -_Optional, Default="zstd, br, gzip"_ +_Optional, Default="gzip, br, zstd"_ `encodings` specifies the list of supported compression encodings. -At least one encoding value must be specified, and valid entries are `zstd` (Zstandard), `br` (Brotli), and `gzip` (Gzip). +At least one encoding value must be specified, and valid entries are `gzip` (Gzip), `br` (Brotli), and `zstd` (Zstandard). The order of the list also sets the priority, the top entry has the highest priority. ```yaml tab="Docker & Swarm" diff --git a/docs/content/migration/v3.md b/docs/content/migration/v3.md index 4f2f1d6e6..fdbf5b513 100644 --- a/docs/content/migration/v3.md +++ b/docs/content/migration/v3.md @@ -187,3 +187,13 @@ and will be removed in the next major version. In `v3.3.4`, the OpenTelemetry Request Duration metric (named `traefik_(entrypoint|router|service)_request_duration_seconds`) unit has been changed from milliseconds to seconds. To be consistent with the naming and other metrics providers, the metric now reports the duration in seconds. + +## v3.3.5 + +### Compress Middleware + +In `v3.3.5`, the compress middleware `encodings` option default value is now `gzip, br, zstd`. +This change helps the algorithm selection to favor the `gzip` algorithm over the other algorithms. + +It impacts requests that do not specify their preferred algorithm, +or has no order preference, in the `Accept-Encoding` header. diff --git a/pkg/config/dynamic/middlewares.go b/pkg/config/dynamic/middlewares.go index 87a464e6c..ea57f4518 100644 --- a/pkg/config/dynamic/middlewares.go +++ b/pkg/config/dynamic/middlewares.go @@ -187,7 +187,7 @@ type Compress struct { } func (c *Compress) SetDefaults() { - c.Encodings = []string{"zstd", "br", "gzip"} + c.Encodings = []string{"gzip", "br", "zstd"} } // +k8s:deepcopy-gen=true diff --git a/pkg/middlewares/compress/acceptencoding.go b/pkg/middlewares/compress/acceptencoding.go index c09c84130..a35362733 100644 --- a/pkg/middlewares/compress/acceptencoding.go +++ b/pkg/middlewares/compress/acceptencoding.go @@ -23,57 +23,44 @@ type Encoding struct { Weight float64 } -func getCompressionEncoding(acceptEncoding []string, defaultEncoding string, supportedEncodings []string) string { - if defaultEncoding == "" { - if slices.Contains(supportedEncodings, brotliName) { - // Keeps the pre-existing default inside Traefik if brotli is a supported encoding. - defaultEncoding = brotliName - } else if len(supportedEncodings) > 0 { - // Otherwise use the first supported encoding. - defaultEncoding = supportedEncodings[0] - } +func (c *compress) getCompressionEncoding(acceptEncoding []string) string { + // RFC says: An Accept-Encoding header field with a field value that is empty implies that the user agent does not want any content coding in response. + // https://datatracker.ietf.org/doc/html/rfc9110#name-accept-encoding + if len(acceptEncoding) == 1 && acceptEncoding[0] == "" { + return identityName } - encodings, hasWeight := parseAcceptEncoding(acceptEncoding, supportedEncodings) + acceptableEncodings := parseAcceptableEncodings(acceptEncoding, c.supportedEncodings) - if hasWeight { - if len(encodings) == 0 { - return identityName - } - - encoding := encodings[0] - - if encoding.Type == identityName && encoding.Weight == 0 { - return notAcceptable - } - - if encoding.Type == wildcardName && encoding.Weight == 0 { - return notAcceptable - } - - if encoding.Type == wildcardName { - return defaultEncoding - } - - return encoding.Type + // An empty Accept-Encoding header field would have been handled earlier. + // If empty, it means no encoding is supported, we do not encode. + if len(acceptableEncodings) == 0 { + // TODO: return 415 status code instead of deactivating the compression, if the backend was not to compress as well. + return notAcceptable } - for _, dt := range supportedEncodings { - if slices.ContainsFunc(encodings, func(e Encoding) bool { return e.Type == dt }) { - return dt + slices.SortFunc(acceptableEncodings, func(a, b Encoding) int { + if a.Weight == b.Weight { + // At same weight, we want to prioritize based on the encoding priority. + // the lower the index, the higher the priority. + return cmp.Compare(c.supportedEncodings[a.Type], c.supportedEncodings[b.Type]) } + return cmp.Compare(b.Weight, a.Weight) + }) + + if acceptableEncodings[0].Type == wildcardName { + if c.defaultEncoding == "" { + return c.encodings[0] + } + + return c.defaultEncoding } - if slices.ContainsFunc(encodings, func(e Encoding) bool { return e.Type == wildcardName }) { - return defaultEncoding - } - - return identityName + return acceptableEncodings[0].Type } -func parseAcceptEncoding(acceptEncoding, supportedEncodings []string) ([]Encoding, bool) { +func parseAcceptableEncodings(acceptEncoding []string, supportedEncodings map[string]int) []Encoding { var encodings []Encoding - var hasWeight bool for _, line := range acceptEncoding { for _, item := range strings.Split(strings.ReplaceAll(line, " ", ""), ",") { @@ -82,9 +69,7 @@ func parseAcceptEncoding(acceptEncoding, supportedEncodings []string) ([]Encodin continue } - if !slices.Contains(supportedEncodings, parsed[0]) && - parsed[0] != identityName && - parsed[0] != wildcardName { + if _, ok := supportedEncodings[parsed[0]]; !ok { continue } @@ -94,8 +79,13 @@ func parseAcceptEncoding(acceptEncoding, supportedEncodings []string) ([]Encodin if len(parsed) > 1 && strings.HasPrefix(parsed[1], "q=") { w, _ := strconv.ParseFloat(strings.TrimPrefix(parsed[1], "q="), 64) + // If the weight is 0, the encoding is not acceptable. + // We can skip the encoding. + if w == 0 { + continue + } + weight = w - hasWeight = true } encodings = append(encodings, Encoding{ @@ -105,9 +95,5 @@ func parseAcceptEncoding(acceptEncoding, supportedEncodings []string) ([]Encodin } } - slices.SortFunc(encodings, func(a, b Encoding) int { - return cmp.Compare(b.Weight, a.Weight) - }) - - return encodings, hasWeight + return encodings } diff --git a/pkg/middlewares/compress/acceptencoding_test.go b/pkg/middlewares/compress/acceptencoding_test.go index 570315b47..d3059af6e 100644 --- a/pkg/middlewares/compress/acceptencoding_test.go +++ b/pkg/middlewares/compress/acceptencoding_test.go @@ -1,9 +1,12 @@ package compress import ( + "context" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/traefik/traefik/v3/pkg/config/dynamic" ) func Test_getCompressionEncoding(t *testing.T) { @@ -15,14 +18,19 @@ func Test_getCompressionEncoding(t *testing.T) { expected string }{ { - desc: "br > gzip (no weight)", - acceptEncoding: []string{"gzip, br"}, - expected: brotliName, + desc: "Empty Accept-Encoding", + acceptEncoding: []string{""}, + expected: identityName, }, { - desc: "zstd > br > gzip (no weight)", - acceptEncoding: []string{"zstd, gzip, br"}, - expected: zstdName, + desc: "gzip > br (no weight)", + acceptEncoding: []string{"gzip, br"}, + expected: gzipName, + }, + { + desc: "gzip > br > zstd (no weight)", + acceptEncoding: []string{"gzip, br, zstd"}, + expected: gzipName, }, { desc: "known compression encoding (no weight)", @@ -32,24 +40,34 @@ func Test_getCompressionEncoding(t *testing.T) { { desc: "unknown compression encoding (no weight), no encoding", acceptEncoding: []string{"compress, rar"}, - expected: identityName, + expected: notAcceptable, }, { - desc: "wildcard return the default compression encoding", + desc: "wildcard returns the default compression encoding", acceptEncoding: []string{"*"}, - expected: brotliName, + expected: gzipName, }, { - desc: "wildcard return the custom default compression encoding", + desc: "wildcard returns the custom default compression encoding", acceptEncoding: []string{"*"}, - defaultEncoding: "foo", - expected: "foo", + defaultEncoding: brotliName, + expected: brotliName, }, { desc: "follows weight", acceptEncoding: []string{"br;q=0.8, gzip;q=1.0, *;q=0.1"}, expected: gzipName, }, + { + desc: "identity with higher weight is preferred", + acceptEncoding: []string{"br;q=0.8, identity;q=1.0"}, + expected: identityName, + }, + { + desc: "identity with equal weight is not preferred", + acceptEncoding: []string{"br;q=0.8, identity;q=0.8"}, + expected: brotliName, + }, { desc: "ignore unknown compression encoding", acceptEncoding: []string{"compress;q=1.0, gzip;q=0.5"}, @@ -93,6 +111,33 @@ func Test_getCompressionEncoding(t *testing.T) { supportedEncodings: []string{gzipName, brotliName}, expected: gzipName, }, + { + desc: "Zero weights, no compression", + acceptEncoding: []string{"br;q=0, gzip;q=0, zstd;q=0"}, + expected: notAcceptable, + }, + { + desc: "Zero weights, default encoding, no compression", + acceptEncoding: []string{"br;q=0, gzip;q=0, zstd;q=0"}, + defaultEncoding: "br", + expected: notAcceptable, + }, + { + desc: "Same weight, first supported encoding", + acceptEncoding: []string{"br;q=1.0, gzip;q=1.0, zstd;q=1.0"}, + expected: gzipName, + }, + { + desc: "Same weight, first supported encoding, order has no effect", + acceptEncoding: []string{"br;q=1.0, zstd;q=1.0, gzip;q=1.0"}, + expected: gzipName, + }, + { + desc: "Same weight, first supported encoding, defaultEncoding has no effect", + acceptEncoding: []string{"br;q=1.0, zstd;q=1.0, gzip;q=1.0"}, + defaultEncoding: "br", + expected: gzipName, + }, } for _, test := range testCases { @@ -103,7 +148,18 @@ func Test_getCompressionEncoding(t *testing.T) { test.supportedEncodings = defaultSupportedEncodings } - encoding := getCompressionEncoding(test.acceptEncoding, test.defaultEncoding, test.supportedEncodings) + conf := dynamic.Compress{ + Encodings: test.supportedEncodings, + DefaultEncoding: test.defaultEncoding, + } + + h, err := New(context.Background(), nil, conf, "test") + require.NoError(t, err) + + c, ok := h.(*compress) + require.True(t, ok) + + encoding := c.getCompressionEncoding(test.acceptEncoding) assert.Equal(t, test.expected, encoding) }) @@ -147,7 +203,6 @@ func Test_parseAcceptEncoding(t *testing.T) { {Type: zstdName, Weight: 1}, {Type: gzipName, Weight: 1}, {Type: brotliName, Weight: 1}, - {Type: wildcardName, Weight: 0}, }, assertWeight: assert.True, }, @@ -157,7 +212,6 @@ func Test_parseAcceptEncoding(t *testing.T) { supportedEncodings: []string{zstdName}, expected: []Encoding{ {Type: zstdName, Weight: 1}, - {Type: wildcardName, Weight: 0}, }, assertWeight: assert.True, }, @@ -188,7 +242,6 @@ func Test_parseAcceptEncoding(t *testing.T) { expected: []Encoding{ {Type: gzipName, Weight: 1}, {Type: identityName, Weight: 0.5}, - {Type: wildcardName, Weight: 0}, }, assertWeight: assert.True, }, @@ -198,7 +251,6 @@ func Test_parseAcceptEncoding(t *testing.T) { supportedEncodings: []string{"br"}, expected: []Encoding{ {Type: identityName, Weight: 0.5}, - {Type: wildcardName, Weight: 0}, }, assertWeight: assert.True, }, @@ -212,10 +264,11 @@ func Test_parseAcceptEncoding(t *testing.T) { test.supportedEncodings = defaultSupportedEncodings } - aes, hasWeight := parseAcceptEncoding(test.values, test.supportedEncodings) + supportedEncodings := buildSupportedEncodings(test.supportedEncodings) + + aes := parseAcceptableEncodings(test.values, supportedEncodings) assert.Equal(t, test.expected, aes) - test.assertWeight(t, hasWeight) }) } } diff --git a/pkg/middlewares/compress/compress.go b/pkg/middlewares/compress/compress.go index cdf4d972b..0bb3788d2 100644 --- a/pkg/middlewares/compress/compress.go +++ b/pkg/middlewares/compress/compress.go @@ -22,7 +22,7 @@ const typeName = "Compress" // See https://github.com/klauspost/compress/blob/9559b037e79ad673c71f6ef7c732c00949014cd2/gzhttp/compress.go#L47. const defaultMinSize = 1024 -var defaultSupportedEncodings = []string{zstdName, brotliName, gzipName} +var defaultSupportedEncodings = []string{gzipName, brotliName, zstdName} // Compress is a middleware that allows to compress the response. type compress struct { @@ -33,6 +33,8 @@ type compress struct { minSize int encodings []string defaultEncoding string + // supportedEncodings is a map of supported encodings and their priority. + supportedEncodings map[string]int brotliHandler http.Handler gzipHandler http.Handler @@ -85,13 +87,14 @@ func New(ctx context.Context, next http.Handler, conf dynamic.Compress, name str } c := &compress{ - next: next, - name: name, - excludes: excludes, - includes: includes, - minSize: minSize, - encodings: conf.Encodings, - defaultEncoding: conf.DefaultEncoding, + next: next, + name: name, + excludes: excludes, + includes: includes, + minSize: minSize, + encodings: conf.Encodings, + defaultEncoding: conf.DefaultEncoding, + supportedEncodings: buildSupportedEncodings(conf.Encodings), } var err error @@ -114,6 +117,19 @@ func New(ctx context.Context, next http.Handler, conf dynamic.Compress, name str return c, nil } +func buildSupportedEncodings(encodings []string) map[string]int { + supportedEncodings := map[string]int{ + // the most permissive first. + wildcardName: -1, + // the less permissive last. + identityName: len(encodings), + } + for i, encoding := range encodings { + supportedEncodings[encoding] = i + } + return supportedEncodings +} + func (c *compress) ServeHTTP(rw http.ResponseWriter, req *http.Request) { logger := middlewares.GetLogger(req.Context(), c.name, typeName) @@ -149,7 +165,7 @@ func (c *compress) ServeHTTP(rw http.ResponseWriter, req *http.Request) { return } - c.chooseHandler(getCompressionEncoding(acceptEncoding, c.defaultEncoding, c.encodings), rw, req) + c.chooseHandler(c.getCompressionEncoding(acceptEncoding), rw, req) } func (c *compress) chooseHandler(typ string, rw http.ResponseWriter, req *http.Request) { diff --git a/pkg/middlewares/compress/compress_test.go b/pkg/middlewares/compress/compress_test.go index 430df7611..622471f2e 100644 --- a/pkg/middlewares/compress/compress_test.go +++ b/pkg/middlewares/compress/compress_test.go @@ -39,9 +39,14 @@ func TestNegotiation(t *testing.T) { expEncoding: "", }, { + // In this test, the default encodings are defaulted to gzip, brotli, and zstd, + // which make gzip the default encoding, and will be selected. + // However, the klauspost/compress gzhttp handler does not compress when Accept-Encoding: * is set. + // Until klauspost/compress gzhttp package supports the asterisk, + // we will not support it when selecting the gzip encoding. desc: "accept any header", acceptEncHeader: "*", - expEncoding: brotliName, + expEncoding: "", }, { desc: "gzip accept header", @@ -66,7 +71,7 @@ func TestNegotiation(t *testing.T) { { desc: "multi accept header list, prefer br", acceptEncHeader: "gzip, br", - expEncoding: brotliName, + expEncoding: gzipName, }, { desc: "zstd accept header", @@ -78,15 +83,20 @@ func TestNegotiation(t *testing.T) { acceptEncHeader: "zstd;q=0.9, br;q=0.8, gzip;q=0.6", expEncoding: zstdName, }, + { + desc: "multi accept header, prefer brotli", + acceptEncHeader: "gzip;q=0.8, br;q=1.0, zstd;q=0.7", + expEncoding: brotliName, + }, { desc: "multi accept header, prefer gzip", acceptEncHeader: "gzip;q=1.0, br;q=0.8, zstd;q=0.7", expEncoding: gzipName, }, { - desc: "multi accept header list, prefer zstd", + desc: "multi accept header list, prefer gzip", acceptEncHeader: "gzip, br, zstd", - expEncoding: zstdName, + expEncoding: gzipName, }, } @@ -190,6 +200,28 @@ func TestShouldNotCompressWhenNoAcceptEncodingHeader(t *testing.T) { assert.EqualValues(t, rw.Body.Bytes(), fakeBody) } +func TestEmptyAcceptEncoding(t *testing.T) { + req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil) + req.Header.Add(acceptEncodingHeader, "") + + fakeBody := generateBytes(gzhttp.DefaultMinSize) + next := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + _, err := rw.Write(fakeBody) + if err != nil { + http.Error(rw, err.Error(), http.StatusInternalServerError) + } + }) + handler, err := New(context.Background(), next, dynamic.Compress{Encodings: defaultSupportedEncodings}, "testing") + require.NoError(t, err) + + rw := httptest.NewRecorder() + handler.ServeHTTP(rw, req) + + assert.Empty(t, rw.Header().Get(contentEncodingHeader)) + assert.Empty(t, rw.Header().Get(varyHeader)) + assert.EqualValues(t, rw.Body.Bytes(), fakeBody) +} + func TestShouldNotCompressWhenIdentityAcceptEncodingHeader(t *testing.T) { req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil) req.Header.Set(acceptEncodingHeader, "identity") From ddb32ef86fbbfe85dfe1a4fb4b5bedf3261b5b97 Mon Sep 17 00:00:00 2001 From: Rohit Lohar <64224488+rohitlohar45@users.noreply.github.com> Date: Fri, 28 Mar 2025 16:06:04 +0530 Subject: [PATCH 15/18] Allow underscore character in hostSNI matcher --- pkg/muxer/tcp/mux.go | 2 +- pkg/muxer/tcp/mux_test.go | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/muxer/tcp/mux.go b/pkg/muxer/tcp/mux.go index 5bf4fbc08..8302ab340 100644 --- a/pkg/muxer/tcp/mux.go +++ b/pkg/muxer/tcp/mux.go @@ -310,7 +310,7 @@ func alpn(tree *matchersTree, protos ...string) error { return nil } -var hostOrIP = regexp.MustCompile(`^[[:alnum:]\.\-\:]+$`) +var hostOrIP = regexp.MustCompile(`^[[:word:]\.\-\:]+$`) // hostSNI checks if the SNI Host of the connection match the matcher host. func hostSNI(tree *matchersTree, hosts ...string) error { diff --git a/pkg/muxer/tcp/mux_test.go b/pkg/muxer/tcp/mux_test.go index 45820acdb..aa3c6b1e6 100644 --- a/pkg/muxer/tcp/mux_test.go +++ b/pkg/muxer/tcp/mux_test.go @@ -743,6 +743,11 @@ func Test_HostSNI(t *testing.T) { ruleHosts: []string{"foo.bar"}, serverName: "foo.bar", }, + { + desc: "Matching hosts with subdomains with _", + ruleHosts: []string{"foo_bar.example.com"}, + serverName: "foo_bar.example.com", + }, { desc: "Matching IPv4", ruleHosts: []string{"127.0.0.1"}, From 6e9d713668d1739d9244561493d1a56fbbb75e5d Mon Sep 17 00:00:00 2001 From: Adam Duke <94930+adamvduke@users.noreply.github.com> Date: Mon, 31 Mar 2025 03:24:06 -0400 Subject: [PATCH 16/18] Bump github.com/vulcand/oxy/v2 to v2.0.3 --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 989743fd7..167a60557 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/golang/protobuf v1.5.4 github.com/google/go-github/v28 v28.1.1 github.com/gorilla/mux v1.8.1 - github.com/gorilla/websocket v1.5.0 + github.com/gorilla/websocket v1.5.3 github.com/hashicorp/consul/api v1.26.1 github.com/hashicorp/go-hclog v1.6.3 github.com/hashicorp/go-multierror v1.1.1 @@ -69,7 +69,7 @@ require ( github.com/uber/jaeger-lib v2.4.1+incompatible github.com/unrolled/render v1.0.2 github.com/unrolled/secure v1.0.9 - github.com/vulcand/oxy/v2 v2.0.0 + github.com/vulcand/oxy/v2 v2.0.3 github.com/vulcand/predicate v1.2.0 go.elastic.co/apm/module/apmot/v2 v2.4.8 go.elastic.co/apm/v2 v2.4.8 diff --git a/go.sum b/go.sum index 8ab908195..e8cc4fc7c 100644 --- a/go.sum +++ b/go.sum @@ -638,8 +638,8 @@ github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+ github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf h1:C1GPyPJrOlJlIrcaBBiBpDsqZena2Ks8spa5xZqr1XQ= github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf/go.mod h1:zXqxTI6jXDdKnlf8s+nT+3c8LrwUEy3yNpO4XJL90lA= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= @@ -1344,8 +1344,8 @@ github.com/vinyldns/go-vinyldns v0.9.16 h1:GZJStDkcCk1F1AcRc64LuuMh+ENL8pHA0CVd4 github.com/vinyldns/go-vinyldns v0.9.16/go.mod h1:5qIJOdmzAnatKjurI+Tl4uTus7GJKJxb+zitufjHs3Q= github.com/volcengine/volc-sdk-golang v1.0.189 h1:VMDTHWYXakXJtZqPYn0As/h4eB0c4imvyru6mIp+o60= github.com/volcengine/volc-sdk-golang v1.0.189/go.mod h1:u0VtPvlXWpXDTmc9IHkaW1q+5Jjwus4oAqRhNMDRInE= -github.com/vulcand/oxy/v2 v2.0.0 h1:V+scHhd2xBjO8ojBRgxCM+OdZxRA/YTs8M70w5tdNy8= -github.com/vulcand/oxy/v2 v2.0.0/go.mod h1:uIAz3sYafO7i+V3SC8oDlMn/lt1i9aWcyXuXqVswKzE= +github.com/vulcand/oxy/v2 v2.0.3 h1:CPWVPfW4hVZXzwwiQzpFidbnJKpahjPHezM+7TkZRNw= +github.com/vulcand/oxy/v2 v2.0.3/go.mod h1:k3t+xjyqmXVh88FdFDbYmUKMEvNpaejvBW14es6H70A= github.com/vulcand/predicate v1.2.0 h1:uFsW1gcnnR7R+QTID+FVcs0sSYlIGntoGOTb3rQJt50= github.com/vulcand/predicate v1.2.0/go.mod h1:VipoNYXny6c8N381zGUWkjuuNHiRbeAZhE7Qm9c+2GA= github.com/vultr/govultr/v3 v3.9.1 h1:uxSIb8Miel7tqTs3ee+z3t+JelZikwqBBsZzCOPBy/8= From b7be71c02a8a03530524ac200cd9e423703bcfef Mon Sep 17 00:00:00 2001 From: Romain Date: Mon, 31 Mar 2025 09:48:04 +0200 Subject: [PATCH 17/18] Prepare release v2.11.22 --- CHANGELOG.md | 21 +++++++++++++++++++++ script/gcg/traefik-bugfix.toml | 6 +++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a48bd088..7f191315d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,24 @@ +## [v2.11.22](https://github.com/traefik/traefik/tree/v2.11.22) (2025-03-31) +[All Commits](https://github.com/traefik/traefik/compare/v2.11.21...v2.11.22) + +**Bug fixes:** +- **[ecs,logs]** Bump AWS SDK to v2 ([#11359](https://github.com/traefik/traefik/pull/11359) by [Juneezee](https://github.com/Juneezee)) +- **[logs,tls]** Error level log for configuration-related TLS errors with backends ([#11611](https://github.com/traefik/traefik/pull/11611) by [rtribotte](https://github.com/rtribotte)) +- **[rules]** Allow underscore character in HostSNI matcher ([#11557](https://github.com/traefik/traefik/pull/11557) by [rohitlohar45](https://github.com/rohitlohar45)) +- **[server]** Bump github.com/vulcand/oxy/v2 to v2.0.3 ([#11649](https://github.com/traefik/traefik/pull/11649) by [adamvduke](https://github.com/adamvduke)) +- **[server]** Bump golang.org/x/net to v0.37.0 ([#11632](https://github.com/traefik/traefik/pull/11632) by [kevinpollet](https://github.com/kevinpollet)) +- **[webui]** Change boolean module properties default value to undefined ([#11639](https://github.com/traefik/traefik/pull/11639) by [rtribotte](https://github.com/rtribotte)) +- Bump github.com/golang-jwt/jwt to v4.5.2 and v5.2.2 ([#11634](https://github.com/traefik/traefik/pull/11634) by [kevinpollet](https://github.com/kevinpollet)) +- Bump github.com/redis/go-redis/v9 to v9.6.3 ([#11633](https://github.com/traefik/traefik/pull/11633) by [kevinpollet](https://github.com/kevinpollet)) +- Bump golang.org/x/net to v0.36.0 ([#11608](https://github.com/traefik/traefik/pull/11608) by [kevinpollet](https://github.com/kevinpollet)) +- Bump github.com/go-jose/go-jose/v4 to v4.0.5 ([#11571](https://github.com/traefik/traefik/pull/11571) by [kevinpollet](https://github.com/kevinpollet)) + +**Documentation:** +- **[accesslogs]** Remove documentation for OriginStatusLine and DownstreamStatusLine accessLogs fields ([#11599](https://github.com/traefik/traefik/pull/11599) by [rtribotte](https://github.com/rtribotte)) +- **[middleware]** Clarifies that retry middleware uses TCP, not HTTP status codes ([#11603](https://github.com/traefik/traefik/pull/11603) by [geraldcroes](https://github.com/geraldcroes)) +- **[redis]** Add tip for dynamic configuration updates of Redis ([#11577](https://github.com/traefik/traefik/pull/11577) by [Alanxtl](https://github.com/Alanxtl)) +- Add Security Support ([#11610](https://github.com/traefik/traefik/pull/11610) by [nmengin](https://github.com/nmengin)) + # [v2.11.21](https://github.com/traefik/traefik/tree/v2.11.21) (2025-02-24) [All Commits](https://github.com/traefik/traefik/compare/v2.11.20...v2.11.21) diff --git a/script/gcg/traefik-bugfix.toml b/script/gcg/traefik-bugfix.toml index 9f83b4d2e..e1d02c8fd 100644 --- a/script/gcg/traefik-bugfix.toml +++ b/script/gcg/traefik-bugfix.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example new bugfix v2.11.21 +# example new bugfix v2.11.22 CurrentRef = "v2.11" -PreviousRef = "v2.11.20" +PreviousRef = "v2.11.21" BaseBranch = "v2.11" -FutureCurrentRefName = "v2.11.21" +FutureCurrentRefName = "v2.11.22" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10 From bd4ff81818904709e5d6811617cea6b84003ae86 Mon Sep 17 00:00:00 2001 From: Romain Date: Mon, 31 Mar 2025 10:38:04 +0200 Subject: [PATCH 18/18] Prepare release v3.3.5 --- CHANGELOG.md | 17 +++++++++++++++++ script/gcg/traefik-bugfix.toml | 6 +++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8242999f..d5c4d8d02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +## [v3.3.5](https://github.com/traefik/traefik/tree/v3.3.5) (2025-03-31) +[All Commits](https://github.com/traefik/traefik/compare/v3.3.4...v3.3.5) + +**Bug fixes:** +- **[k8s/gatewayapi]** Set scheme to https with BackendTLSPolicy ([#11586](https://github.com/traefik/traefik/pull/11586) by [rtribotte](https://github.com/rtribotte)) +- **[middleware]** Revert compress middleware algorithms priority to v2 behavior ([#11641](https://github.com/traefik/traefik/pull/11641) by [rtribotte](https://github.com/rtribotte)) +- **[middleware]** Do not abort request when response content-type is malformed ([#11628](https://github.com/traefik/traefik/pull/11628) by [kevinpollet](https://github.com/kevinpollet)) +- **[middleware]** Compress data on flush when compression is not started ([#11583](https://github.com/traefik/traefik/pull/11583) by [kevinpollet](https://github.com/kevinpollet)) + +**Documentation:** +- **[middleware]** Add back forwarded headers section in FAQ ([#11606](https://github.com/traefik/traefik/pull/11606) by [kevinpollet](https://github.com/kevinpollet)) +- New Routing Reference Documentation ([#11330](https://github.com/traefik/traefik/pull/11330) by [sheddy-traefik](https://github.com/sheddy-traefik)) + +**Misc:** +- Merge branch v2.11 into v3.3 ([#11644](https://github.com/traefik/traefik/pull/11644) by [kevinpollet](https://github.com/kevinpollet)) +- Merge branch v2.11 into v3.3 ([#11594](https://github.com/traefik/traefik/pull/11594) by [rtribotte](https://github.com/rtribotte)) + ## [v2.11.22](https://github.com/traefik/traefik/tree/v2.11.22) (2025-03-31) [All Commits](https://github.com/traefik/traefik/compare/v2.11.21...v2.11.22) diff --git a/script/gcg/traefik-bugfix.toml b/script/gcg/traefik-bugfix.toml index f8c76f1e8..1aa3ab605 100644 --- a/script/gcg/traefik-bugfix.toml +++ b/script/gcg/traefik-bugfix.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example new bugfix v3.3.4 +# example new bugfix v3.3.5 CurrentRef = "v3.3" -PreviousRef = "v3.3.3" +PreviousRef = "v3.3.4" BaseBranch = "v3.3" -FutureCurrentRefName = "v3.3.4" +FutureCurrentRefName = "v3.3.5" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10