Merge branch v3.6 into v3.7

This commit is contained in:
mmatur 2026-04-29 15:24:01 +02:00
commit de40e88d31
No known key found for this signature in database
GPG Key ID: 2FFE42FC256CFF8E
16 changed files with 151 additions and 26 deletions

View File

@ -1,3 +1,26 @@
## [v3.6.15](https://github.com/traefik/traefik/tree/v3.6.15) (2026-04-29)
[All Commits](https://github.com/traefik/traefik/compare/v3.6.14...v3.6.15)
**Bug fixes:**
- **[acme]** Bump github.com/go-acme/lego/v4 to v4.35.2 ([#13043](https://github.com/traefik/traefik/pull/13043) @ldez)
- **[acme]** Bump github.com/go-acme/lego/v4 to v4.35.1 ([#13027](https://github.com/traefik/traefik/pull/13027) @ldez)
- **[middleware]** Add errorRequestHeaders option to Errors middleware ([#13034](https://github.com/traefik/traefik/pull/13034) @gndz07)
- **[k8s/ingress-nginx]** Do not require a port for ExternalName services ([#13033](https://github.com/traefik/traefik/pull/13033) @kevinpollet)
- **[server]** Bump github.com/vulcand/oxy to v2.1.0 ([#13046](https://github.com/traefik/traefik/pull/13046) @ldez)
**Misc:**
- Make FLAGS Make variable usable ([#13009](https://github.com/traefik/traefik/pull/13009) @twz123)
## [v2.11.44](https://github.com/traefik/traefik/tree/v2.11.44) (2026-04-29)
[All Commits](https://github.com/traefik/traefik/compare/v2.11.43...v2.11.44)
**Bug fixes:**
- **[middleware]** Add errorRequestHeaders option to Errors middleware ([#13034](https://github.com/traefik/traefik/pull/13034) @gndz07)
- **[acme]** Bump github.com/go-acme/lego to v4.35.2 ([#13052](https://github.com/traefik/traefik/pull/13052) @mmatur)
**Misc:**
- Make FLAGS Make variable usable ([#13009](https://github.com/traefik/traefik/pull/13009) @twz123)
## [v3.7.0-rc.2](https://github.com/traefik/traefik/tree/v3.7.0-rc.2) (2026-04-22)
[All Commits](https://github.com/traefik/traefik/compare/v3.7.0-rc.1...v3.7.0-rc.2)

View File

@ -58,7 +58,7 @@ generate:
#? binary: Build the binary
binary: generate-webui dist
@echo SHA: $(VERSION) $(CODENAME) $(DATE)
CGO_ENABLED=0 GOGC=${GOGC} GOOS=${GOOS} GOARCH=${GOARCH} go build ${FLAGS[*]} -ldflags "-s -w \
CGO_ENABLED=0 GOGC=${GOGC} GOOS=${GOOS} GOARCH=${GOARCH} go build ${FLAGS} -ldflags "-s -w \
-X github.com/traefik/traefik/v3/pkg/version.Version=$(VERSION) \
-X github.com/traefik/traefik/v3/pkg/version.Codename=$(CODENAME) \
-X github.com/traefik/traefik/v3/pkg/version.BuildDate=$(DATE)" \

View File

@ -80,6 +80,15 @@ Note: TLSOptions for `HostRegexp` matchers remains unsupported. Use wildcard `Ho
---
## v3.6.15
In `v3.6.15`, a new `errorRequestHeaders` option has been added to the Errors middleware.
By default, the behavior is unchanged: all original request headers are forwarded to the error page service.
If the error page service is in a separate trust domain, consider using `errorRequestHeaders` to restrict which headers are forwarded.
Please check out the [Error Pages](../reference/routing-configuration/http/middlewares/errorpages.md#errorRequestHeaders) middleware documentation for more details.
## v3.6.14
### Kubernetes CRD: Chain middleware and `allowCrossNamespace`

View File

@ -30,6 +30,7 @@
- "traefik.http.middlewares.middleware08.digestauth.removeheader=true"
- "traefik.http.middlewares.middleware08.digestauth.users=foobar, foobar"
- "traefik.http.middlewares.middleware08.digestauth.usersfile=foobar"
- "traefik.http.middlewares.middleware09.errors.errorrequestheaders=foobar, foobar"
- "traefik.http.middlewares.middleware09.errors.query=foobar"
- "traefik.http.middlewares.middleware09.errors.service=foobar"
- "traefik.http.middlewares.middleware09.errors.status=foobar, foobar"

View File

@ -193,6 +193,7 @@
status = ["foobar", "foobar"]
service = "foobar"
query = "foobar"
errorRequestHeaders = ["foobar", "foobar"]
[http.middlewares.Middleware09.errors.statusRewrites]
name0 = 42
name1 = 42

View File

@ -208,6 +208,9 @@ http:
name1: 42
service: foobar
query: foobar
errorRequestHeaders:
- foobar
- foobar
Middleware10:
forwardAuth:
address: foobar

View File

@ -129,3 +129,12 @@ The table below lists all the available variables and their associated values.
| <a id="opt-status-2" href="#opt-status-2" title="#opt-status-2">`{status}`</a> | The response status code. |
| <a id="opt-originalStatus" href="#opt-originalStatus" title="#opt-originalStatus">`{originalStatus}`</a> | The original response status code, if it has been modified by the `statusRewrites` option. |
| <a id="opt-url" href="#opt-url" title="#opt-url">`{url}`</a> | The [escaped](https://pkg.go.dev/net/url#QueryEscape) request URL.|
### `errorRequestHeaders`
Defines the list of original request headers forwarded to the error page service.
By default (`errorRequestHeaders` not set), all request headers — including authentication material such as `Authorization` and `Cookie` — are forwarded.
If the error page service is in a separate trust domain, use this option to restrict which headers cross the service boundary.
Set to an explicit list to forward only those headers, or set to an empty list (`errorRequestHeaders: []`) to forward no headers.

View File

@ -209,6 +209,7 @@
status = ["foobar", "foobar"]
service = "foobar"
query = "foobar"
errorRequestHeaders = ["foobar", "foobar"]
[http.middlewares.Middleware10.errors.statusRewrites]
name0 = 42
name1 = 42

View File

@ -232,6 +232,9 @@ http:
name1: 42
service: foobar
query: foobar
errorRequestHeaders:
- foobar
- foobar
Middleware11:
forwardAuth:
address: foobar

13
go.mod
View File

@ -24,7 +24,7 @@ require (
github.com/docker/go-connections v0.6.0
github.com/fatih/structs v1.1.0
github.com/fsnotify/fsnotify v1.9.0
github.com/go-acme/lego/v4 v4.35.1
github.com/go-acme/lego/v4 v4.35.2
github.com/go-kit/kit v0.13.0
github.com/go-kit/log v0.2.1
github.com/golang/protobuf v1.5.4
@ -78,7 +78,7 @@ require (
github.com/unrolled/render v1.0.2
github.com/unrolled/secure v1.0.9
github.com/valyala/fasthttp v1.69.0
github.com/vulcand/oxy/v2 v2.0.3
github.com/vulcand/oxy/v2 v2.1.0
github.com/vulcand/predicate v1.3.0
github.com/yuin/gopher-lua v1.1.1
go.opentelemetry.io/collector/pdata v1.41.0
@ -148,7 +148,7 @@ require (
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 // indirect
github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect
github.com/HdrHistogram/hdrhistogram-go v1.2.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.4.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
@ -245,7 +245,7 @@ require (
github.com/googleapis/gax-go/v2 v2.21.0 // indirect
github.com/gophercloud/gophercloud v1.14.1 // indirect
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 // indirect
github.com/gravitational/trace v1.5.0 // indirect
github.com/gravitational/trace v1.5.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect
github.com/hashicorp/cronexpr v1.1.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
@ -285,7 +285,7 @@ require (
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect
github.com/magiconair/properties v1.8.10 // indirect
github.com/mailgun/minheap v0.0.0-20170619185613-3dbe6c6bf55f // indirect
github.com/mailgun/multibuf v0.1.2 // indirect
github.com/mailgun/multibuf v0.2.0 // indirect
github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51 // indirect
github.com/mailru/easyjson v0.9.1 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
@ -319,7 +319,7 @@ require (
github.com/nrdcg/namesilo v0.5.0 // indirect
github.com/nrdcg/nodion v0.1.0 // indirect
github.com/nrdcg/oci-go-sdk/common/v1065 v1065.113.0 // indirect
github.com/nrdcg/oci-go-sdk/dns/v1065 v1065.112.0 // indirect
github.com/nrdcg/oci-go-sdk/dns/v1065 v1065.113.0 // indirect
github.com/nrdcg/porkbun v0.4.0 // indirect
github.com/nrdcg/vegadns v0.3.0 // indirect
github.com/nzdjb/go-metaname v1.0.0 // indirect
@ -427,7 +427,6 @@ replace (
github.com/abbot/go-http-auth => github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e
github.com/gorilla/mux => github.com/containous/mux v0.0.0-20250523120546-41b6ec3aed59
github.com/mailgun/minheap => github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595
github.com/vulcand/oxy/v2 => github.com/traefik/oxy/v2 v2.0.0-20260126093803-fb11d60e0fdf
)
// ambiguous import: found package github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/http in multiple modules

23
go.sum
View File

@ -662,8 +662,9 @@ github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM=
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
github.com/HdrHistogram/hdrhistogram-go v1.2.0 h1:XMJkDWuz6bM9Fzy7zORuVFKH7ZJY41G2q8KWhVGkNiY=
github.com/HdrHistogram/hdrhistogram-go v1.2.0/go.mod h1:CiIeGiHSd06zjX+FypuEJ5EQ07KKtxZ+8J6hszwVQig=
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
@ -1027,8 +1028,8 @@ github.com/go-acme/esa-20240910/v2 v2.48.0 h1:muSDyhjDTejxUGe3FTthCPCqRaEdYY9cG3
github.com/go-acme/esa-20240910/v2 v2.48.0/go.mod h1:shPb6hzc1rJL15IJBY8HQ4GZk4E8RC52+52twutEwIg=
github.com/go-acme/jdcloud-sdk-go v1.64.0 h1:AW9j5khk8tRYbpBJPxKmqdwIqgLs2Fz3HUK3hn2YXjs=
github.com/go-acme/jdcloud-sdk-go v1.64.0/go.mod h1:qc/m8HNX1Zgd7GAv2DSEinup8fwy3Ted3/VVx7LB5bU=
github.com/go-acme/lego/v4 v4.35.1 h1:xTcEBsENs4Ek5EiNpN3JXy7W5aynf5KhJ6D/HuuhXv4=
github.com/go-acme/lego/v4 v4.35.1/go.mod h1:E+4l5mPPg9dwhTz6JJptNLvtj94E2JDObI50QuFJd3s=
github.com/go-acme/lego/v4 v4.35.2 h1:uVQg+KC/yj9R2g7Q9W5wDqhvQvxV5SMu5eqFVoN5xZU=
github.com/go-acme/lego/v4 v4.35.2/go.mod h1:pX2jN5n8OphMGY1IaMjYm5DAEzguBaKRt8AvJAgJXpc=
github.com/go-acme/tencentclouddnspod v1.3.24 h1:uCSiOW1EJttcnOON+MVVyVDJguFL/Q4NIGkq1CrT9p8=
github.com/go-acme/tencentclouddnspod v1.3.24/go.mod h1:RKcB2wSoZncjBA0OEFj59s1ko1XDy+ZsAtk+9uMxUF0=
github.com/go-acme/tencentedgdeone v1.3.38 h1:5YsVl0H4A+cwtiUqR1eZbKFdr4OWfYp2KYJopifzKyQ=
@ -1293,8 +1294,8 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
github.com/gravitational/trace v1.5.0 h1:JbeL2HDGyzgy7G72Z2hP2gExEyA6Y2p7fCiSjyZwCJw=
github.com/gravitational/trace v1.5.0/go.mod h1:dxezSkKm880IIDx+czWG8fq+pLnXjETBewMgN3jOBlg=
github.com/gravitational/trace v1.5.1 h1:CdSymAjkE1VOef+lsC5x29jX9WbgI0fBtnRqeT4Fh+c=
github.com/gravitational/trace v1.5.1/go.mod h1:sJKfJHIQ7IkG8kvYpFPEr6mj3WDEdZ0YAc7xAD8w7lw=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
@ -1536,8 +1537,8 @@ github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mailgun/multibuf v0.1.2 h1:QE9kE27lK6LFZB4aYNVtUPlWVHVCT0zpgUr2uoq/+jk=
github.com/mailgun/multibuf v0.1.2/go.mod h1:E+sUhIy69qgT6EM57kCPdUTlHnjTuxQBO/yf6af9Hes=
github.com/mailgun/multibuf v0.2.0 h1:pGhv93r0GXBVTDu6RMlA9GUQjwwoy4yspIujtaT0AOA=
github.com/mailgun/multibuf v0.2.0/go.mod h1:E+sUhIy69qgT6EM57kCPdUTlHnjTuxQBO/yf6af9Hes=
github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51 h1:Kg/NPZLLC3aAFr1YToMs98dbCdhootQ1hZIvZU28hAQ=
github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51/go.mod h1:RYmqHbhWwIz3z9eVmQ2rx82rulEMG0t+Q1bzfc9DYN4=
github.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f h1:ZZYhg16XocqSKPGNQAe0aeweNtFxuedbwwb4fSlg7h4=
@ -1688,8 +1689,8 @@ github.com/nrdcg/nodion v0.1.0 h1:zLKaqTn2X0aDuBHHfyA1zFgeZfiCpmu/O9DM73okavw=
github.com/nrdcg/nodion v0.1.0/go.mod h1:inbuh3neCtIWlMPZHtEpe43TmRXxHV6+hk97iCZicms=
github.com/nrdcg/oci-go-sdk/common/v1065 v1065.113.0 h1:OLlJVGHkTHBCXdTGpNn5ay4DV3gOZrVLxlUM6xBQrIM=
github.com/nrdcg/oci-go-sdk/common/v1065 v1065.113.0/go.mod h1:Gcs8GCaZXL3FdiDWgdnMxlOLEdRprJJnPYB22TX1jw8=
github.com/nrdcg/oci-go-sdk/dns/v1065 v1065.112.0 h1:sQ9SfyNFj4u2kStSd2ZbsU12b4nNyROK307fb3hkoPk=
github.com/nrdcg/oci-go-sdk/dns/v1065 v1065.112.0/go.mod h1:DaABHQaJMe64ppbXBsJPEESLxXRrbkiDfkR9JFeFowY=
github.com/nrdcg/oci-go-sdk/dns/v1065 v1065.113.0 h1:bveOZN6gZZjjEM1T9o1TUm8de3zePyDbfuluMpaRJCE=
github.com/nrdcg/oci-go-sdk/dns/v1065 v1065.113.0/go.mod h1:Ff6Cxm43tuGJHyltQwD3EXLs7kKpkxzqy6DGQcaiS/0=
github.com/nrdcg/porkbun v0.4.0 h1:rWweKlwo1PToQ3H+tEO9gPRW0wzzgmI/Ob3n2Guticw=
github.com/nrdcg/porkbun v0.4.0/go.mod h1:/QMskrHEIM0IhC/wY7iTCUgINsxdT2WcOphktJ9+Q54=
github.com/nrdcg/vegadns v0.3.0 h1:11FQMw7xVIRUWO9o5+Z/5YZhmPWlm4oxUUH3F6EVqQU=
@ -1993,8 +1994,6 @@ github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XV
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/traefik/grpc-web v0.16.0 h1:eeUWZaFg6ZU0I9dWOYE2D5qkNzRBmXzzuRlxdltascY=
github.com/traefik/grpc-web v0.16.0/go.mod h1:2ttniSv7pTgBWIU2HZLokxRfFX3SA60c/DTmQQgVml4=
github.com/traefik/oxy/v2 v2.0.0-20260126093803-fb11d60e0fdf h1:qOjmGqgXvycy0+tda6rWhTPulgQxnImwRrM1AROIvJ4=
github.com/traefik/oxy/v2 v2.0.0-20260126093803-fb11d60e0fdf/go.mod h1:as06A23Znc9S/ilJpKqJ/UhO3Zu5JztlxVwQuKl+iZs=
github.com/traefik/paerser v0.2.2 h1:cpzW/ZrQrBh3mdwD/jnp6aXASiUFKOVr6ldP+keJTcQ=
github.com/traefik/paerser v0.2.2/go.mod h1:7BBDd4FANoVgaTZG+yh26jI6CA2nds7D/4VTEdIsh24=
github.com/traefik/yaegi v0.16.1 h1:f1De3DVJqIDKmnasUF6MwmWv1dSEEat0wcpXhD2On3E=
@ -2034,6 +2033,8 @@ github.com/vinyldns/go-vinyldns v0.9.17 h1:hfPZfCaxcRBX6Gsgl42rLCeoal58/BH8kkvJS
github.com/vinyldns/go-vinyldns v0.9.17/go.mod h1:pwWhE9K/leGDOIduVhRGvQ3ecVMHWRfEnKYUTEU3gB4=
github.com/volcengine/volc-sdk-golang v1.0.242 h1:YEnYLl8mn83JCdO/X5GRDvxfxGvpUqk5j0Mj4VhwM6Y=
github.com/volcengine/volc-sdk-golang v1.0.242/go.mod h1:zHJlaqiMbIB+0mcrsZPTwOb3FB7S/0MCfqlnO8R7hlM=
github.com/vulcand/oxy/v2 v2.1.0 h1:JnFb/qz+o96E6NEl4X6WSmNmcrlccPmCIyhAZLBVLWM=
github.com/vulcand/oxy/v2 v2.1.0/go.mod h1:9kY0wYBlMqrgXCZTNYCwE89NYwGGdM3sSD+w59CKMhw=
github.com/vulcand/predicate v1.3.0 h1:jtNe4PHbLJ649dR7Gl+MSAzUhLGtLspAkWlSjoOiXg8=
github.com/vulcand/predicate v1.3.0/go.mod h1:opzv9MetRuMNnuoPeTSWtwzjcXsxQC00/fuWzkPTn4s=
github.com/vultr/govultr/v3 v3.31.0 h1:xSRqIQEnB3tjgpIOADWQOhOedDsqZj9qawW+mAoq7/8=

View File

@ -271,6 +271,10 @@ type ErrorPage struct {
// The {originalStatus} variable can be used in order to insert the upstream status code in the URL.
// The {url} variable can be used in order to insert the escaped request URL.
Query string `json:"query,omitempty" toml:"query,omitempty" yaml:"query,omitempty" export:"true"`
// ErrorRequestHeaders defines the list of request headers forwarded to the error page service.
// When nil (not set), all original request headers are forwarded.
// Set to an empty list to forward no headers, or list specific headers to forward only those.
ErrorRequestHeaders []string `json:"errorRequestHeaders,omitempty" toml:"errorRequestHeaders,omitempty" yaml:"errorRequestHeaders,omitempty" export:"true"`
// NginxHeaders defines the headers to forward to the Error page service.
// NginxHeaders option is unexposed to other providers than the IngressNGINX one.

View File

@ -381,6 +381,11 @@ func (in *ErrorPage) DeepCopyInto(out *ErrorPage) {
(*out)[key] = val
}
}
if in.ErrorRequestHeaders != nil {
in, out := &in.ErrorRequestHeaders, &out.ErrorRequestHeaders
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.NginxHeaders != nil {
in, out := &in.NginxHeaders, &out.NginxHeaders
*out = new(http.Header)

View File

@ -38,6 +38,7 @@ type customErrors struct {
backendHandler http.Handler
httpCodeRanges types.HTTPCodeRanges
backendQuery string
requestHeaders []string
statusRewrites []statusRewrite
forwardNginxHeaders http.Header
}
@ -81,6 +82,7 @@ func New(ctx context.Context, next http.Handler, config dynamic.ErrorPage, servi
backendHandler: backend,
httpCodeRanges: httpCodeRanges,
backendQuery: config.Query,
requestHeaders: config.ErrorRequestHeaders,
statusRewrites: statusRewrites,
forwardNginxHeaders: ptr.Deref(config.NginxHeaders, nil),
}, nil
@ -148,6 +150,16 @@ func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
return
}
if c.requestHeaders != nil {
for _, header := range c.requestHeaders {
if values := req.Header.Values(header); len(values) > 0 {
pageReq.Header[http.CanonicalHeaderKey(header)] = values
}
}
} else {
utils.CopyHeaders(pageReq.Header, req.Header)
}
if len(c.forwardNginxHeaders) > 0 {
utils.CopyHeaders(pageReq.Header, c.forwardNginxHeaders)
pageReq.Header.Set("X-Code", strconv.Itoa(code))
@ -156,11 +168,7 @@ func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if requestID := req.Header.Get("X-Request-ID"); requestID != "" {
pageReq.Header.Set("X-Request-ID", requestID)
}
} else {
utils.CopyHeaders(pageReq.Header, req.Header)
}
if len(c.forwardNginxHeaders) > 0 {
c.backendHandler.ServeHTTP(rw, pageReq.WithContext(req.Context()))
} else {
c.backendHandler.ServeHTTP(newCodeModifier(rw, code),

View File

@ -23,6 +23,7 @@ func TestHandler(t *testing.T) {
backendCode int
backendErrorHandler http.HandlerFunc
validate func(t *testing.T, recorder *httptest.ResponseRecorder)
requestHeaders map[string]string
}{
{
desc: "no error",
@ -154,6 +155,60 @@ func TestHandler(t *testing.T) {
assert.Contains(t, recorder.Body.String(), "My 503 page.")
},
},
{
desc: "forward all headers by default",
errorPage: &dynamic.ErrorPage{Service: "error", Query: "/test", Status: []string{"503"}},
requestHeaders: map[string]string{
"X-Request-Id": "trace-abc",
"Authorization": "Bearer secret",
},
backendCode: http.StatusServiceUnavailable,
backendErrorHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, r.Header.Get("X-Request-Id"))
fmt.Fprintln(w, r.Header.Get("Authorization"))
}),
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
t.Helper()
assert.Contains(t, recorder.Body.String(), "trace-abc")
assert.Contains(t, recorder.Body.String(), "Bearer secret")
},
},
{
desc: "forward only allowlisted headers",
errorPage: &dynamic.ErrorPage{Service: "error", Query: "/test", Status: []string{"503"}, ErrorRequestHeaders: []string{"X-Request-Id"}},
requestHeaders: map[string]string{
"X-Request-Id": "trace-abc",
"Authorization": "Bearer secret",
},
backendCode: http.StatusServiceUnavailable,
backendErrorHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, r.Header.Get("X-Request-Id"))
fmt.Fprintln(w, r.Header.Get("Authorization"))
}),
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
t.Helper()
assert.Contains(t, recorder.Body.String(), "trace-abc")
assert.NotContains(t, recorder.Body.String(), "Bearer secret")
},
},
{
desc: "forward no headers",
errorPage: &dynamic.ErrorPage{Service: "error", Query: "/test", Status: []string{"503"}, ErrorRequestHeaders: []string{}},
requestHeaders: map[string]string{
"X-Request-Id": "trace-abc",
"Authorization": "Bearer secret",
},
backendCode: http.StatusServiceUnavailable,
backendErrorHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, r.Header.Get("X-Request-Id"))
fmt.Fprintln(w, r.Header.Get("Authorization"))
}),
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
t.Helper()
assert.NotContains(t, recorder.Body.String(), "trace-abc")
assert.NotContains(t, recorder.Body.String(), "Bearer secret")
},
},
{
desc: "nginx headers: backend status code preserved",
errorPage: &dynamic.ErrorPage{
@ -253,6 +308,9 @@ func TestHandler(t *testing.T) {
require.NoError(t, err)
req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost/test?foo=bar&baz=buz", nil)
for k, v := range test.requestHeaders {
req.Header.Set(k, v)
}
// Client like browser and curl will issue a relative HTTP request, which not have a host and scheme in the URL. But the http.NewRequest will set them automatically.
req.URL.Host = ""

View File

@ -4,11 +4,11 @@ RepositoryName = "traefik"
OutputType = "file"
FileName = "traefik_changelog.md"
# example new bugfix v3.6.14
# example new bugfix v3.6.15
CurrentRef = "v3.6"
PreviousRef = "v3.6.13"
PreviousRef = "v3.6.14"
BaseBranch = "v3.6"
FutureCurrentRefName = "v3.6.14"
FutureCurrentRefName = "v3.6.15"
ThresholdPreviousRef = 10000
ThresholdCurrentRef = 10000