1
0
mirror of https://github.com/containous/traefik.git synced 2026-01-18 00:34:10 +03:00

Compare commits

...

8 Commits

Author SHA1 Message Date
Michael
51343bc15f Upgrade golangci-lint 2026-01-14 17:26:08 +01:00
Kevin Pollet
9e5d4ba5a1 Prepare release v2.11.35 2026-01-14 10:28:04 +01:00
Gina A.
adf47fba31 Make encoded character options opt-in 2026-01-14 10:16:04 +01:00
Sheddy
ee265a8509 Add Scarf Analytics to documentation 2026-01-13 11:16:05 +01:00
Barbara Soraggi
fc67185987 Replace markdown-include dependency with mkdocs-include-markdown-plugin 2026-01-13 10:08:04 +01:00
Michel Loiseleur
e8067f4e01 Refactor CI on documentation 2026-01-09 17:24:04 +01:00
LBF38
e9f3089e90 Add timeout to ACME-TLS/1 challenge handshake
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2026-01-08 16:16:05 +01:00
Michael
47d7094dfb Welcome 2026 2026-01-02 09:58:04 +01:00
336 changed files with 1994 additions and 1770 deletions

63
.github/workflows/check_doc.yaml vendored Normal file
View File

@@ -0,0 +1,63 @@
name: Check Documentation
on:
pull_request:
branches:
- '*'
paths:
- '.github/workflows/check_doc.yaml'
- 'docs/**'
jobs:
docs:
name: lint, build and verify
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Install markdownlint
run: |
npm install --global markdownlint@0.29.0 markdownlint-cli@0.35.0
- name: Lint
run: ./docs/scripts/lint.sh docs
- name: Setup python
uses: actions/setup-python@v6
with:
python-version: '3.12'
cache: 'pip'
cache-dependency-path: "./docs/requirements.txt"
- name: Build documentation
working-directory: ./docs
run: |
pip install -r requirements.txt
mkdocs build --strict
- name: Setup ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.4'
- name: Install html-proofer
run: |
gem install nokogiri --version 1.18.6 --no-document -- --use-system-libraries
gem install html-proofer --version 5.0.10 --no-document -- --use-system-libraries
env:
NOKOGIRI_USE_SYSTEM_LIBRARIES: "true"
# Comes from https://github.com/gjtorikian/html-proofer?tab=readme-ov-file#caching-with-continuous-integration
- name: Cache HTMLProofer
uses: actions/cache@v4
with:
path: tmp/.htmlproofer
key: ${{ runner.os }}-htmlproofer
- name: Verify
run: ./docs/scripts/verify.sh docs/site

View File

@@ -1,25 +0,0 @@
name: Check Documentation
on:
pull_request:
branches:
- '*'
jobs:
docs:
name: Check, verify and build documentation
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Check documentation
run: make docs-pull-images docs
env:
# These variables are not passed to workflows that are triggered by a pull request from a fork.
DOCS_VERIFY_SKIP: ${{ vars.DOCS_VERIFY_SKIP }}
DOCS_LINT_SKIP: ${{ vars.DOCS_LINT_SKIP }}

View File

@@ -7,8 +7,8 @@ on:
env:
GO_VERSION: '1.24'
GOLANGCI_LINT_VERSION: v2.0.2
MISSPELL_VERSION: v0.6.0
GOLANGCI_LINT_VERSION: v2.7.2
MISSPELL_VERSION: v0.7.0
jobs:

View File

@@ -36,6 +36,7 @@ linters:
- nilnil # Not relevant
- nlreturn # Not relevant
- noctx # Too strict
- noinlineerr # Too strict
- nonamedreturns # Too strict
- paralleltest # Not relevant
- prealloc # Too many false-positive.
@@ -47,6 +48,7 @@ linters:
- varnamelen # Not relevant
- wrapcheck # Too strict
- wsl # Too strict
- wsl_v5 # Too strict
settings:
depguard:
@@ -292,15 +294,31 @@ linters:
source: 'errors.New\("Nomad provider'
text: 'ST1005: error strings should not be capitalized'
- path: (.+)\.go
text: 'struct-tag: unknown option ''inline'' in JSON tag'
text: 'omitzero: Omitempty has no effect on nested struct field'
linters:
- modernize
- path: (.+)\.go
text: 'struct-tag: unknown option "inline" in json tag'
linters:
- revive
- path: (.+)\.go
text: 'struct-tag: unknown option ''omitzero'' in TOML tag'
text: 'struct-tag: unknown option "omitzero" in toml tag'
linters:
- revive
- path: (pkg/types/.+|pkg/api/.+)\.go
text: 'var-naming: avoid meaningless package names'
linters:
- revive
- path: (pkg/muxer/http/.+|pkg/provider/http/.+)\.go
text: 'var-naming: avoid package names that conflict with Go standard library package names'
linters:
- revive
- path: (.+)\.go$
text: 'SA1019: http.CloseNotifier has been deprecated' # FIXME must be fixed
- path: (.+)\.go$
text: 'SA1019: dynamic.(TCPIPWhiteList|IPWhiteList) is deprecated: please use IPAllowList instead.'
- path: (.+)\.go$
text: 'SA1019: middlewareTCP.Spec.IPWhiteList is deprecated: please use IPAllowList instead.'
- path: (.+)\.go$
text: 'SA1019: cfg.(SSLRedirect|SSLTemporaryRedirect|SSLHost|SSLForceHost|FeaturePolicy) is deprecated'
- path: (.+)\.go$

View File

@@ -1,3 +1,10 @@
## [v2.11.35](https://github.com/traefik/traefik/tree/v2.11.35) (2026-01-14)
[All Commits](https://github.com/traefik/traefik/compare/v2.11.34...v2.11.35)
**Bug fixes:**
- **[acme]** Add timeout to ACME-TLS/1 challenge handshake ([#12516](https://github.com/traefik/traefik/pull/12516) by [LBF38](https://github.com/LBF38))
- **[server]** Make encoded character options opt-in ([#12540](https://github.com/traefik/traefik/pull/12540) by [gndz07](https://github.com/gndz07))
## [v2.11.34](https://github.com/traefik/traefik/tree/v2.11.34) (2025-12-23)
[All Commits](https://github.com/traefik/traefik/compare/v2.11.33...v2.11.34)

View File

@@ -10,6 +10,7 @@ import (
// TraefikCmdConfiguration wraps the static configuration and extra parameters.
type TraefikCmdConfiguration struct {
static.Configuration `export:"true"`
// ConfigFile is the path to the configuration file.
ConfigFile string `description:"Configuration file to use. If specified all other flags are ignored." export:"true"`
}

View File

@@ -83,7 +83,7 @@ func run(dest string) error {
return err
}
return os.WriteFile(filepath.Join(dest, "marshaler.go"), []byte(fmt.Sprintf(marsh, destPkg)), 0o666)
return os.WriteFile(filepath.Join(dest, "marshaler.go"), fmt.Appendf(nil, marsh, destPkg), 0o666)
}
func cleanType(typ types.Type, base string) string {

View File

@@ -87,10 +87,10 @@ Complete documentation is available at https://traefik.io`,
func runCmd(staticConfiguration *static.Configuration) error {
configureLogging(staticConfiguration)
// Display warning to advertise for new behavior of rejecting encoded characters in the request path.
// Deprecated: this has to be removed in the next minor/major version.
log.WithoutContext().Warnf("Starting with v2.11.32, Traefik now rejects some encoded characters in the request path by default. " +
"Refer to the documentation for more details: https://doc.traefik.io/traefik/v2.11/migration/v2/#encoded-characters-in-request-path")
log.WithoutContext().Warn("Traefik can reject some encoded characters in the request path." +
"When your backend is not fully compliant with [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986)," +
"it is recommended to set these options to `false` to avoid split-view situation." +
"Refer to the documentation for more details: https://doc.traefik.io/traefik/v2.11/migration/v2/#encoded-characters-configuration-default-values")
http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment

View File

@@ -1,4 +1,14 @@
/* Highlight */
(function(hljs) {
hljs.initHighlightingOnLoad();
})(hljs);
})(hljs);
/* Scarf Analytics - cookieless, anonymous company-level intelligence */
(function() {
var img = document.createElement('img');
img.src = 'https://static.scarf.sh/a.png?x-pxid=1a49232a-b165-4015-8ed2-a1092f1f0d83';
img.referrerPolicy = 'no-referrer-when-downgrade';
img.loading = 'eager';
img.style.cssText = 'visibility:hidden;position:absolute;width:1px;height:1px;';
document.body.appendChild(img);
})();

View File

@@ -34,7 +34,7 @@ Below is a non-exhaustive list of versions and their maintenance status:
This page is maintained and updated periodically to reflect our roadmap and any decisions affecting the end of support for Traefik Proxy.
Please refer to our migration guides for specific instructions on upgrading between versions, an example is the [v2 to v3 migration guide](../migration/v2-to-v3.md).
Please refer to our migration guides for specific instructions on upgrading between versions.
!!! important "All target dates for end of support or feature removal announcements may be subject to change."

View File

@@ -57,4 +57,4 @@ You no longer need to create and synchronize configuration files cluttered with
Traefik is able to use your cluster API to discover the services and read the attached information.
In Traefik, these connectors are called [providers](../providers/overview.md "Link to overview about Traefik providers") because they *provide* the configuration to Traefik.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -94,4 +94,4 @@ All the configuration options are documented in their related section.
You can browse the available features in the menu, the [providers](../providers/overview.md), or the [routing section](../routing/overview.md) to see them in action.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -252,4 +252,4 @@ In which case, you should make sure your infrastructure is properly set up for a
LEGO_DISABLE_CNAME_SUPPORT=true
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -144,4 +144,4 @@ And run it:
All the details are available in the [Contributing Guide](../contributing/building-testing.md)
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -334,4 +334,4 @@ curl -v http://localhost/
- Use [IngressRoute CRD](../providers/kubernetes-crd.md)
- Protect [ingresses with TLS](../routing/providers/kubernetes-ingress.md#enabling-tls-via-annotations)
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -121,4 +121,4 @@ IP: 172.27.0.4
Now that you have a basic understanding of how Traefik can automatically create the routes to your services and load balance them, it is time to dive into [the user guides](../../user-guides/docker-compose/basic-example/ "Link to the user guides") and [the documentation](/ "Link to the docs landing page") and let Traefik work for you!
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -797,4 +797,4 @@ If Let's Encrypt is not reachable, the following certificates will apply:
!!! important
For new (sub)domains which need Let's Encrypt authentication, the default Traefik certificate will be used until Traefik is restarted.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -20,4 +20,4 @@ That is to say, how to obtain [TLS certificates](./tls.md#certificates-definitio
either through a definition in the dynamic configuration, or through [Let's Encrypt](./acme.md) (ACME).
And how to configure [TLS options](./tls.md#tls-options), and [certificates stores](./tls.md#certificates-stores).
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -561,4 +561,4 @@ spec:
clientAuthType: RequireAndVerifyClientCert
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -404,4 +404,4 @@ http:
[http.middlewares.test-auth.basicAuth]
removeHeader = true
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -637,4 +637,4 @@ http:
[http.middlewares.test-auth.forwardAuth.tls]
insecureSkipVerify: true
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -480,4 +480,4 @@ Set `isDevelopment` to `true` when developing to mitigate the unwanted effects o
Usually testing takes place using HTTP, not HTTPS, and on `localhost`, not your production domain.
If you would like your development environment to mimic production with complete Host blocking, SSL redirects, and STS headers, leave this as `false`.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -158,4 +158,4 @@ http:
Please take a look at the community-contributed plugins in the [plugin catalog](https://plugins.traefik.io/plugins).
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -100,4 +100,4 @@ The `replacement` option defines how to modify the URL to have the new target UR
Care should be taken when defining replacement expand variables: `$1x` is equivalent to `${1x}`, not `${1}x` (see [Regexp.Expand](https://golang.org/pkg/regexp/#Regexp.Expand)), so use `${1}` syntax.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -171,4 +171,4 @@ http:
forceSlash = false
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -130,4 +130,4 @@ A list of HTTP middlewares can be found [here](http/overview.md).
A list of TCP middlewares can be found [here](tcp/overview.md).
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -737,3 +737,30 @@ Note: This check is not done against query parameters,
but only against the request path as defined in [RFC3986 section-3](https://datatracker.ietf.org/doc/html/rfc3986#section-3).
Please check out the entrypoint [encodedCharacters option](../routing/entrypoints.md#encoded-characters) documentation for more details.
## v2.11.35
### Encoded Characters Configuration Default Values
Since `v2.11.35`, the options for encoded characters now have a `true` default value.
This means that Traefik will not reject requests with a path containing a specific set of encoded characters by default.
It is now up to the users to configure the security hardening of encoded characters.
Here is the list of the encoded characters that can be configured to `false` to disallow them:
| Encoded Character | Character | Config options | Default value |
|-------------------|-------------------------|--------------------------------------------------------------------------------------|---------------|
| `%2f` or `%2F` | `/` (slash) | `entryPoints.<name>`<br/>`.http.encodedCharacters`<br/>`.allowEncodedSlash` | `true` |
| `%5c` or `%5C` | `\` (backslash) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedBackSlash` | `true` |
| `%00` | `NULL` (null character) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedNullCharacter` | `true` |
| `%3b` or `%3B` | `;` (semicolon) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedSemicolon` | `true` |
| `%25` | `%` (percent) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedPercent` | `true` |
| `%3f` or `%3F` | `?` (question mark) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedQuestionMark` | `true` |
| `%23` | `#` (hash) | `entryPoints.<name>.`<br/>`.http.encodedCharacters`<br/>`.allowEncodedHash` | `true` |
Note: This check is not done against query parameters,
but only against the request path as defined
in [RFC3986 section-3](https://datatracker.ietf.org/doc/html/rfc3986#section-3).
Please check out the entrypoint [encodedCharacters option](../routing/entrypoints.md#encoded-characters) documentation
for more details.

View File

@@ -281,4 +281,4 @@ services:
- /var/run/docker.sock:/var/run/docker.sock
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -90,4 +90,4 @@ This allows the logs to be rotated and processed by an external program, such as
!!! warning
This does not work on Windows due to the lack of USR signals.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -175,4 +175,4 @@ All the following endpoints must be accessed with a `GET` HTTP request.
| `/debug/pprof/symbol` | See the [pprof Symbol](https://golang.org/pkg/net/http/pprof/#Symbol) Go documentation. |
| `/debug/pprof/trace` | See the [pprof Trace](https://golang.org/pkg/net/http/pprof/#Trace) Go documentation. |
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -132,4 +132,4 @@ api:
--api.dashboard=false
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -31,4 +31,4 @@ The experience of implementing a Traefik plugin is comparable to writing a web b
To learn more about Traefik plugin creation, please refer to the [developer documentation](https://plugins.traefik.io/create).
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -764,4 +764,4 @@ providers:
--providers.docker.allowEmptyServices=true
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -292,4 +292,4 @@ To illustrate, it is possible to easily define multiple routers, services, and T
{{ end }}
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -345,4 +345,4 @@ providers:
For additional information, refer to the [full example](../user-guides/crd-acme/index.md) with Let's Encrypt.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -269,4 +269,4 @@ providers:
--providers.kubernetesgateway.throttleDuration=10s
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -504,4 +504,4 @@ providers:
To learn more about the various aspects of the Ingress specification that Traefik supports,
many examples of Ingresses definitions are located in the test [examples](https://github.com/traefik/traefik/tree/v2.11/pkg/provider/kubernetes/ingress/fixtures) of the Traefik repository.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -233,4 +233,4 @@ List of providers that support constraints:
- [Kubernetes Ingress](./kubernetes-ingress.md#labelselector)
- [Kubernetes Gateway](./kubernetes-gateway.md#labelselector)
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -1273,6 +1273,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
ipStrategy:
@@ -1663,8 +1664,9 @@ spec:
description: |-
IPWhiteList defines the IPWhiteList middleware configuration.
This middleware accepts/refuses connections based on the client IP.
Deprecated: please use IPAllowList instead.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
sourceRange:
description: SourceRange defines the allowed IPs (or ranges of
@@ -1907,6 +1909,7 @@ spec:
description: |-
PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's.
It is enabled automatically when minVersion or maxVersion is set.
Deprecated: https://github.com/golang/go/issues/45430
type: boolean
sniStrict:
@@ -3703,6 +3706,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
ipStrategy:
@@ -4093,8 +4097,9 @@ spec:
description: |-
IPWhiteList defines the IPWhiteList middleware configuration.
This middleware accepts/refuses connections based on the client IP.
Deprecated: please use IPAllowList instead.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
sourceRange:
description: SourceRange defines the allowed IPs (or ranges of
@@ -4337,6 +4342,7 @@ spec:
description: |-
PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's.
It is enabled automatically when minVersion or maxVersion is set.
Deprecated: https://github.com/golang/go/issues/45430
type: boolean
sniStrict:

View File

@@ -36,4 +36,4 @@ Dynamic configuration with Kubernetes Custom Resource
--8<-- "content/reference/dynamic-configuration/kubernetes-crd-rbac.yml"
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -30,4 +30,4 @@ Dynamic configuration with Kubernetes Gateway provider.
--8<-- "content/reference/dynamic-configuration/kubernetes-gateway-rbac.yml"
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -658,6 +658,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
ipStrategy:

View File

@@ -68,8 +68,9 @@ spec:
description: |-
IPWhiteList defines the IPWhiteList middleware configuration.
This middleware accepts/refuses connections based on the client IP.
Deprecated: please use IPAllowList instead.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
sourceRange:
description: SourceRange defines the allowed IPs (or ranges of

View File

@@ -99,6 +99,7 @@ spec:
description: |-
PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's.
It is enabled automatically when minVersion or maxVersion is set.
Deprecated: https://github.com/golang/go/issues/45430
type: boolean
sniStrict:

View File

@@ -658,6 +658,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
ipStrategy:

View File

@@ -68,8 +68,9 @@ spec:
description: |-
IPWhiteList defines the IPWhiteList middleware configuration.
This middleware accepts/refuses connections based on the client IP.
Deprecated: please use IPAllowList instead.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
sourceRange:
description: SourceRange defines the allowed IPs (or ranges of

View File

@@ -99,6 +99,7 @@ spec:
description: |-
PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's.
It is enabled automatically when minVersion or maxVersion is set.
Deprecated: https://github.com/golang/go/issues/45430
type: boolean
sniStrict:

View File

@@ -124,25 +124,25 @@ Trust only forwarded headers from selected IPs.
HTTP configuration.
`--entrypoints.<name>.http.encodedcharacters.allowencodedbackslash`:
Defines whether requests with encoded back slash characters in the path are allowed. (Default: ```false```)
Defines whether requests with encoded back slash characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodedhash`:
Defines whether requests with encoded hash characters in the path are allowed. (Default: ```false```)
Defines whether requests with encoded hash characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodednullcharacter`:
Defines whether requests with encoded null characters in the path are allowed. (Default: ```false```)
Defines whether requests with encoded null characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodedpercent`:
Defines whether requests with encoded percent characters in the path are allowed. (Default: ```false```)
Defines whether requests with encoded percent characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodedquestionmark`:
Defines whether requests with encoded question mark characters in the path are allowed. (Default: ```false```)
Defines whether requests with encoded question mark characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodedsemicolon`:
Defines whether requests with encoded semicolon characters in the path are allowed. (Default: ```false```)
Defines whether requests with encoded semicolon characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodedcharacters.allowencodedslash`:
Defines whether requests with encoded slash characters in the path are allowed. (Default: ```false```)
Defines whether requests with encoded slash characters in the path are allowed. (Default: ```true```)
`--entrypoints.<name>.http.encodequerysemicolons`:
Defines whether request query semicolons should be URLEncoded. (Default: ```false```)

View File

@@ -133,25 +133,25 @@ HTTP/3 configuration. (Default: ```false```)
UDP port to advertise, on which HTTP/3 is available. (Default: ```0```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDBACKSLASH`:
Defines whether requests with encoded back slash characters in the path are allowed. (Default: ```false```)
Defines whether requests with encoded back slash characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDHASH`:
Defines whether requests with encoded hash characters in the path are allowed. (Default: ```false```)
Defines whether requests with encoded hash characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDNULLCHARACTER`:
Defines whether requests with encoded null characters in the path are allowed. (Default: ```false```)
Defines whether requests with encoded null characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDPERCENT`:
Defines whether requests with encoded percent characters in the path are allowed. (Default: ```false```)
Defines whether requests with encoded percent characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDQUESTIONMARK`:
Defines whether requests with encoded question mark characters in the path are allowed. (Default: ```false```)
Defines whether requests with encoded question mark characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDSEMICOLON`:
Defines whether requests with encoded semicolon characters in the path are allowed. (Default: ```false```)
Defines whether requests with encoded semicolon characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDSLASH`:
Defines whether requests with encoded slash characters in the path are allowed. (Default: ```false```)
Defines whether requests with encoded slash characters in the path are allowed. (Default: ```true```)
`TRAEFIK_ENTRYPOINTS_<NAME>_HTTP_ENCODEQUERYSEMICOLONS`:
Defines whether request query semicolons should be URLEncoded. (Default: ```false```)

View File

@@ -129,13 +129,13 @@ They can be defined by using a file (YAML or TOML) or CLI arguments.
- "192.168.0.1"
http:
encodedCharacters:
allowEncodedSlash: true
allowEncodedBackSlash: true
allowEncodedNullCharacter: true
allowEncodedSemicolon: true
allowEncodedPercent: true
allowEncodedQuestionMark: true
allowEncodedHash: true
allowEncodedSlash: false
allowEncodedBackSlash: false
allowEncodedNullCharacter: false
allowEncodedSemicolon: false
allowEncodedPercent: false
allowEncodedQuestionMark: false
allowEncodedHash: false
```
```toml tab="File (TOML)"
@@ -162,13 +162,13 @@ They can be defined by using a file (YAML or TOML) or CLI arguments.
insecure = true
trustedIPs = ["127.0.0.1", "192.168.0.1"]
[entryPoints.name.http.encodedCharacters]
allowEncodedSlash = true
allowEncodedBackSlash = true
allowEncodedNullCharacter = true
allowEncodedSemicolon = true
allowEncodedPercent = true
allowEncodedQuestionMark = true
allowEncodedHash = true
allowEncodedSlash = false
allowEncodedBackSlash = false
allowEncodedNullCharacter = false
allowEncodedSemicolon = false
allowEncodedPercent = false
allowEncodedQuestionMark = false
allowEncodedHash = false
```
```bash tab="CLI"
@@ -185,13 +185,13 @@ They can be defined by using a file (YAML or TOML) or CLI arguments.
--entryPoints.name.proxyProtocol.trustedIPs=127.0.0.1,192.168.0.1
--entryPoints.name.forwardedHeaders.insecure=true
--entryPoints.name.forwardedHeaders.trustedIPs=127.0.0.1,192.168.0.1
--entryPoints.name.http.encodedCharacters.allowEncodedSlash=true
--entryPoints.name.http.encodedCharacters.allowEncodedBackSlash=true
--entryPoints.name.http.encodedCharacters.allowEncodedNullCharacter=true
--entryPoints.name.http.encodedCharacters.allowEncodedSemicolon=true
--entryPoints.name.http.encodedCharacters.allowEncodedPercent=true
--entryPoints.name.http.encodedCharacters.allowEncodedQuestionMark=true
--entryPoints.name.http.encodedCharacters.allowEncodedHash=true
--entryPoints.name.http.encodedCharacters.allowEncodedSlash=false
--entryPoints.name.http.encodedCharacters.allowEncodedBackSlash=false
--entryPoints.name.http.encodedCharacters.allowEncodedNullCharacter=false
--entryPoints.name.http.encodedCharacters.allowEncodedSemicolon=false
--entryPoints.name.http.encodedCharacters.allowEncodedPercent=false
--entryPoints.name.http.encodedCharacters.allowEncodedQuestionMark=false
--entryPoints.name.http.encodedCharacters.allowEncodedHash=false
```
### Address
@@ -1021,20 +1021,21 @@ entryPoints:
### Encoded Characters
You can configure Traefik to control the handling of encoded characters in request paths for security purposes.
By default, Traefik rejects requests with path containing certain encoded characters that could be used in path traversal or other security attacks.
By default, Traefik do not reject requests with path containing certain encoded characters that could be used in path traversal or other security attacks.
!!! info
This check is not done against the request query parameters,
but only against the request path as defined in [RFC3986 section-3](https://datatracker.ietf.org/doc/html/rfc3986#section-3).
!!! warning "Security Considerations"
!!! info "Security Considerations"
Allowing certain encoded characters may expose your application to security vulnerabilities.
When your backend is not fully compliant with [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) and notably decode encoded reserved characters in the requets path,
it is recommended to set these options to `false` to avoid split-view situation and helps prevent path traversal attacks or other malicious attempts to bypass security controls.
??? info "`encodedCharacters.allowEncodedSlash`"
_Optional, Default=false_
_Optional, Default=true_
Controls whether requests with encoded slash characters (`%2F` or `%2f`) in the path are allowed.
@@ -1045,7 +1046,7 @@ By default, Traefik rejects requests with path containing certain encoded charac
address: ":80"
http:
encodedCharacters:
allowEncodedSlash: true
allowEncodedSlash: false
```
```toml tab="File (TOML)"
@@ -1055,18 +1056,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
address = ":80"
[entryPoints.web.http.encodedCharacters]
allowEncodedSlash = true
allowEncodedSlash = false
```
```bash tab="CLI"
## Static configuration
--entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedSlash=true
--entryPoints.web.http.encodedCharacters.allowEncodedSlash=false
```
??? info "`encodedCharacters.allowEncodedBackSlash`"
_Optional, Default=false_
_Optional, Default=true_
Controls whether requests with encoded back slash characters (`%5C` or `%5c`) in the path are allowed.
@@ -1077,7 +1078,7 @@ By default, Traefik rejects requests with path containing certain encoded charac
address: ":80"
http:
encodedCharacters:
allowEncodedBackSlash: true
allowEncodedBackSlash: false
```
```toml tab="File (TOML)"
@@ -1087,18 +1088,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
address = ":80"
[entryPoints.web.http.encodedCharacters]
allowEncodedBackSlash = true
allowEncodedBackSlash = false
```
```bash tab="CLI"
## Static configuration
--entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedBackSlash=true
--entryPoints.web.http.encodedCharacters.allowEncodedBackSlash=false
```
??? info "`encodedCharacters.allowEncodedNullCharacter`"
_Optional, Default=false_
_Optional, Default=true_
Controls whether requests with encoded null characters (`%00`) in the path are allowed.
@@ -1109,7 +1110,7 @@ By default, Traefik rejects requests with path containing certain encoded charac
address: ":80"
http:
encodedCharacters:
allowEncodedNullCharacter: true
allowEncodedNullCharacter: false
```
```toml tab="File (TOML)"
@@ -1119,18 +1120,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
address = ":80"
[entryPoints.web.http.encodedCharacters]
allowEncodedNullCharacter = true
allowEncodedNullCharacter = false
```
```bash tab="CLI"
## Static configuration
--entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedNullCharacter=true
--entryPoints.web.http.encodedCharacters.allowEncodedNullCharacter=false
```
??? info "`encodedCharacters.allowEncodedSemicolon`"
_Optional, Default=false_
_Optional, Default=true_
Controls whether requests with encoded semicolon characters (`%3B` or `%3b`) in the path are allowed.
@@ -1141,7 +1142,7 @@ By default, Traefik rejects requests with path containing certain encoded charac
address: ":80"
http:
encodedCharacters:
allowEncodedSemicolon: true
allowEncodedSemicolon: false
```
```toml tab="File (TOML)"
@@ -1151,18 +1152,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
address = ":80"
[entryPoints.web.http.encodedCharacters]
allowEncodedSemicolon = true
allowEncodedSemicolon = false
```
```bash tab="CLI"
## Static configuration
--entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedSemicolon=true
--entryPoints.web.http.encodedCharacters.allowEncodedSemicolon=false
```
??? info "`encodedCharacters.allowEncodedPercent`"
_Optional, Default=false_
_Optional, Default=true_
Controls whether requests with encoded percent characters (`%25`) in the path are allowed.
@@ -1173,7 +1174,7 @@ By default, Traefik rejects requests with path containing certain encoded charac
address: ":80"
http:
encodedCharacters:
allowEncodedPercent: true
allowEncodedPercent: false
```
```toml tab="File (TOML)"
@@ -1183,18 +1184,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
address = ":80"
[entryPoints.web.http.encodedCharacters]
allowEncodedPercent = true
allowEncodedPercent = false
```
```bash tab="CLI"
## Static configuration
--entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedPercent=true
--entryPoints.web.http.encodedCharacters.allowEncodedPercent=false
```
??? info "`encodedCharacters.allowEncodedQuestionMark`"
_Optional, Default=false_
_Optional, Default=true_
Controls whether requests with encoded question mark characters (`%3F` or `%3f`) in the path are allowed.
@@ -1205,7 +1206,7 @@ By default, Traefik rejects requests with path containing certain encoded charac
address: ":80"
http:
encodedCharacters:
allowEncodedQuestionMark: true
allowEncodedQuestionMark: false
```
```toml tab="File (TOML)"
@@ -1215,18 +1216,18 @@ By default, Traefik rejects requests with path containing certain encoded charac
address = ":80"
[entryPoints.web.http.encodedCharacters]
allowEncodedQuestionMark = true
allowEncodedQuestionMark = false
```
```bash tab="CLI"
## Static configuration
--entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedQuestionMark=true
--entryPoints.web.http.encodedCharacters.allowEncodedQuestionMark=false
```
??? info "`encodedCharacters.allowEncodedHash`"
_Optional, Default=false_
_Optional, Default=true_
Controls whether requests with encoded hash characters (`%23`) in the path are allowed.
@@ -1237,7 +1238,7 @@ By default, Traefik rejects requests with path containing certain encoded charac
address: ":80"
http:
encodedCharacters:
allowEncodedHash: true
allowEncodedHash: false
```
```toml tab="File (TOML)"
@@ -1247,13 +1248,13 @@ By default, Traefik rejects requests with path containing certain encoded charac
address = ":80"
[entryPoints.web.http.encodedCharacters]
allowEncodedHash = true
allowEncodedHash = false
```
```bash tab="CLI"
## Static configuration
--entryPoints.web.address=:80
--entryPoints.web.http.encodedCharacters.allowEncodedHash=true
--entryPoints.web.http.encodedCharacters.allowEncodedHash=false
```
### SanitizePath
@@ -1441,4 +1442,4 @@ entryPoints:
--entryPoints.foo.udp.timeout=10s
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -412,4 +412,4 @@ serversTransport:
--serversTransport.forwardingTimeouts.idleConnTimeout=1s
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -1904,4 +1904,4 @@ If the ServersTransport CRD is defined in another provider the cross-provider fo
Also see the [full example](../../user-guides/crd-acme/index.md) with Let's Encrypt.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -355,4 +355,4 @@ Kubernetes cluster before creating `TLSRoute` objects.
| [11] | `group` | Group is the group of the referent. Only `traefik.io`, `traefik.containo.us` and `gateway.networking.k8s.io` values are supported. |
| [12] | `kind` | Kind is kind of the referent. Only `TraefikService` and `Service` values are supported. |
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -969,4 +969,4 @@ This will allow users to create a "default router" that will match all unmatched
To do this, use the `traefik.ingress.kubernetes.io/router.priority` annotation (as seen in [Annotations on Ingress](#on-ingress)) on your ingresses accordingly.
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -1349,4 +1349,4 @@ Services are the target for the router.
!!! important "UDP routers can only target UDP services (and not HTTP or TCP services)."
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -1646,4 +1646,4 @@ udp:
address = "private-ip-server-2:8080/"
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -20,7 +20,7 @@ When Traefik receives an HTTP request, it processes the request path through sev
Traefik inspects the path for potentially dangerous encoded characters and rejects requests containing them unless explicitly allowed.
Here is the list of the encoded characters that are rejected by default:
Here is the list of the encoded characters that are allowed by default:
| Encoded Character | Character |
|-------------------|-------------------------|
@@ -87,7 +87,12 @@ Configure it in the [EntryPoints](../routing/entrypoints.md#encoded-characters)
This filtering occurs before path sanitization and catches attack attempts that use encoding to bypass other security controls.
All encoded character filtering is enabled by default (`false` means encoded characters are rejected), providing maximum security:
All encoded character filtering is disabled by default (`true` means encoded characters are allowed).
!!! info "Security Considerations"
When your backend is not fully compliant with [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) and notably decode encoded reserved characters in the requets path,
it is recommended to set these options to `false` to avoid split-view situation and helps prevent path traversal attacks or other malicious attempts to bypass security controls.
```yaml tab="File (YAML)"
entryPoints:
@@ -95,13 +100,13 @@ entryPoints:
address: ":443"
http:
encodedCharacters:
allowEncodedSlash: false # %2F - Default: false (RECOMMENDED)
allowEncodedBackSlash: false # %5C - Default: false (RECOMMENDED)
allowEncodedNullCharacter: false # %00 - Default: false (RECOMMENDED)
allowEncodedSemicolon: false # %3B - Default: false (RECOMMENDED)
allowEncodedPercent: false # %25 - Default: false (RECOMMENDED)
allowEncodedQuestionMark: false # %3F - Default: false (RECOMMENDED)
allowEncodedHash: false # %23 - Default: false (RECOMMENDED)
allowEncodedSlash: false # %2F - Default: true
allowEncodedBackSlash: false # %5C - Default: true
allowEncodedNullCharacter: false # %00 - Default: true
allowEncodedSemicolon: false # %3B - Default: true
allowEncodedPercent: false # %25 - Default: true
allowEncodedQuestionMark: false # %3F - Default: true
allowEncodedHash: false # %23 - Default: true
```
```toml tab="File (TOML)"

View File

@@ -187,4 +187,4 @@ environment:
- "OVH_CONSUMER_KEY_FILE=/run/secrets/ovh_consumer_key"
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -83,4 +83,4 @@ labels:
- "traefik.http.routers.whoami.tls.certresolver=myresolver"
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -133,4 +133,4 @@ whoami:
- "traefik.http.routers.whoami.entrypoints=web"
```
{!traefik-for-business-applications.md!}
{% include-markdown "includes/traefik-for-business-applications.md" %}

View File

@@ -2,18 +2,19 @@ site_name: Traefik
site_description: Traefik Documentation
site_author: traefik.io
site_url: https://doc.traefik.io/traefik
dev_addr: 0.0.0.0:8000
dev_addr: localhost:8000
repo_name: 'GitHub'
repo_url: 'https://github.com/traefik/traefik'
docs_dir: 'content'
product: proxy
# https://squidfunk.github.io/mkdocs-material/
# Use custom version of mkdocs-material
# See https://github.com/traefik/mkdocs-material
theme:
name: 'traefik-labs'
product: proxy
language: en
include_sidebar: true
favicon: assets/img/traefikproxy-icon-color.png
@@ -27,7 +28,7 @@ theme:
prev: 'Previous'
next: 'Next'
copyright: 'Traefik Labs • Copyright &copy; 2016-2025'
copyright: 'Traefik Labs • Copyright &copy; 2016-2026'
extra_javascript:
- assets/js/hljs/highlight.pack.js # Download from https://highlightjs.org/download/ and enable YAML, TOML and Dockerfile
@@ -38,6 +39,8 @@ plugins:
- exclude:
glob:
- "**/include-*.md"
- include-markdown:
encoding: utf-8
# https://squidfunk.github.io/mkdocs-material/extensions/admonition/
# https://facelessuser.github.io/pymdown-extensions/
@@ -55,9 +58,6 @@ markdown_extensions:
- pymdownx.tasklist
- pymdownx.snippets:
check_paths: true
- markdown_include.include:
base_path: content/includes/
encoding: utf-8
- toc:
permalink: true
@@ -165,7 +165,6 @@ nav:
- 'Instana': 'observability/tracing/instana.md'
- 'Haystack': 'observability/tracing/haystack.md'
- 'Elastic': 'observability/tracing/elastic.md'
- 'OpenTelemetry': 'observability/tracing/opentelemetry.md'
- 'Security':
- 'Request Path': 'security/request-path.md'
- 'Content-Length': 'security/content-length.md'

View File

@@ -16,3 +16,15 @@
[pymdown-extensions]: https://facelessuser.github.io/pymdown-extensions "PyMdown Extensions"
[pymdown-extensions-src]: https://github.com/facelessuser/pymdown-extensions "PyMdown Extensions - Sources"
## Build locally without docker
```sh
# Pre-requisite: python3, pip and virtualenv
DOCS="/tmp/traefik-docs"
mkdir "$DOCS"
virtualenv "$DOCS"
source "$DOCS/bin/activate"
pip install -r requirements.txt
mkdocs serve # or mkdocs build
```

View File

@@ -1,5 +1,5 @@
markdown-include==0.5.1
mkdocs==1.2.4
mkdocs==1.4.3
mkdocs-include-markdown-plugin==7.2.0
mkdocs-exclude==1.0.2
mkdocs-traefiklabs>=100.0.7

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# This script will run a couple of linter on the documentation
set -eu
@@ -6,14 +6,14 @@ set -eu
# We want to run all linters before returning success (exit 0) or failure (exit 1)
# So this variable holds the global exit code
EXIT_CODE=0
readonly BASE_DIR=/app
readonly BASE_DIR="${1:-/app}"
echo "== Linting Markdown"
# Uses the file ".markdownlint.json" for setup
cd "${BASE_DIR}" || exit 1
LINTER_EXCLUSIONS="$(find "${BASE_DIR}/content" -type f -name '.markdownlint.json')"
GLOBAL_LINT_OPTIONS="--config ${BASE_DIR}/.markdownlint.json"
LINTER_EXCLUSIONS="$(find "content" -type f -name '.markdownlint.json')"
GLOBAL_LINT_OPTIONS="--config .markdownlint.json"
# Lint the specific folders (containing linter specific rulesets)
for LINTER_EXCLUSION in ${LINTER_EXCLUSIONS}
@@ -24,6 +24,6 @@ do
done
# Lint all the content, excluding the previously done`
eval markdownlint "${GLOBAL_LINT_OPTIONS}" "${BASE_DIR}/content/**/*.md" || EXIT_CODE=1
eval markdownlint "${GLOBAL_LINT_OPTIONS}" "content/**/*.md" || EXIT_CODE=1
exit "${EXIT_CODE}"

View File

@@ -245,8 +245,7 @@ func digestParts(resp *http.Response) map[string]string {
result := map[string]string{}
if len(resp.Header["Www-Authenticate"]) > 0 {
wantedHeaders := []string{"nonce", "realm", "qop", "opaque"}
responseHeaders := strings.Split(resp.Header["Www-Authenticate"][0], ",")
for _, r := range responseHeaders {
for r := range strings.SplitSeq(resp.Header["Www-Authenticate"][0], ",") {
for _, w := range wantedHeaders {
if strings.Contains(r, w) {
result[w] = strings.Split(r, `"`)[1]

View File

@@ -27,6 +27,7 @@ import (
// ACME test suites.
type AcmeSuite struct {
BaseSuite
pebbleIP string
fakeDNSServer *dns.Server
}
@@ -63,11 +64,6 @@ const (
wildcardDomain = "*.acme.wtf"
)
func (s *AcmeSuite) getAcmeURL() string {
return fmt.Sprintf("https://%s/dir",
net.JoinHostPort(s.pebbleIP, "14000"))
}
func setupPebbleRootCA() (*http.Transport, error) {
path, err := filepath.Abs("fixtures/acme/ssl/pebble.minica.pem")
if err != nil {
@@ -540,3 +536,8 @@ func (s *AcmeSuite) retrieveAcmeCertificate(testCase acmeTestCase) {
assert.Equal(s.T(), sub.expectedAlgorithm, gotPublicKeyAlgorithm)
}
}
func (s *AcmeSuite) getAcmeURL() string {
return fmt.Sprintf("https://%s/dir",
net.JoinHostPort(s.pebbleIP, "14000"))
}

View File

@@ -16,6 +16,7 @@ import (
type ConsulCatalogSuite struct {
BaseSuite
consulClient *api.Client
consulAgentClient *api.Client
consulURL string
@@ -53,47 +54,6 @@ func (s *ConsulCatalogSuite) TearDownSuite() {
s.BaseSuite.TearDownSuite()
}
func (s *ConsulCatalogSuite) waitToElectConsulLeader() error {
return try.Do(15*time.Second, func() error {
leader, err := s.consulClient.Status().Leader()
if err != nil || len(leader) == 0 {
return fmt.Errorf("leader not found. %w", err)
}
return nil
})
}
func (s *ConsulCatalogSuite) waitForConnectCA() error {
return try.Do(15*time.Second, func() error {
caroots, _, err := s.consulClient.Connect().CARoots(nil)
if err != nil || len(caroots.Roots) == 0 {
return fmt.Errorf("connect CA not fully initialized. %w", err)
}
return nil
})
}
func (s *ConsulCatalogSuite) registerService(reg *api.AgentServiceRegistration, onAgent bool) error {
client := s.consulClient
if onAgent {
client = s.consulAgentClient
}
return client.Agent().ServiceRegister(reg)
}
func (s *ConsulCatalogSuite) deregisterService(id string, onAgent bool) error {
client := s.consulClient
if onAgent {
client = s.consulAgentClient
}
return client.Agent().ServiceDeregister(id)
}
func (s *ConsulCatalogSuite) TestWithNotExposedByDefaultAndDefaultsSettings() {
reg1 := &api.AgentServiceRegistration{
ID: "whoami1",
@@ -847,3 +807,44 @@ func (s *ConsulCatalogSuite) TestConsulConnect_NotAware() {
err = s.deregisterService("whoami1", false)
require.NoError(s.T(), err)
}
func (s *ConsulCatalogSuite) waitToElectConsulLeader() error {
return try.Do(15*time.Second, func() error {
leader, err := s.consulClient.Status().Leader()
if err != nil || len(leader) == 0 {
return fmt.Errorf("leader not found. %w", err)
}
return nil
})
}
func (s *ConsulCatalogSuite) waitForConnectCA() error {
return try.Do(15*time.Second, func() error {
caroots, _, err := s.consulClient.Connect().CARoots(nil)
if err != nil || len(caroots.Roots) == 0 {
return fmt.Errorf("connect CA not fully initialized. %w", err)
}
return nil
})
}
func (s *ConsulCatalogSuite) registerService(reg *api.AgentServiceRegistration, onAgent bool) error {
client := s.consulClient
if onAgent {
client = s.consulAgentClient
}
return client.Agent().ServiceRegister(reg)
}
func (s *ConsulCatalogSuite) deregisterService(id string, onAgent bool) error {
client := s.consulClient
if onAgent {
client = s.consulAgentClient
}
return client.Agent().ServiceDeregister(id)
}

View File

@@ -26,6 +26,7 @@ import (
// Consul test suites.
type ConsulSuite struct {
BaseSuite
kvClient store.Store
consulURL string
}
@@ -164,16 +165,6 @@ func (s *ConsulSuite) TestSimpleConfiguration() {
}
}
func (s *ConsulSuite) assertWhoami(host string, expectedStatusCode int) {
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
require.NoError(s.T(), err)
req.Host = host
resp, err := try.ResponseUntilStatusCode(req, 15*time.Second, expectedStatusCode)
require.NoError(s.T(), err)
resp.Body.Close()
}
func (s *ConsulSuite) TestDeleteRootKey() {
// This test case reproduce the issue: https://github.com/traefik/traefik/issues/8092
@@ -222,3 +213,13 @@ func (s *ConsulSuite) TestDeleteRootKey() {
s.assertWhoami("kv1.localhost", http.StatusNotFound)
s.assertWhoami("kv2.localhost", http.StatusNotFound)
}
func (s *ConsulSuite) assertWhoami(host string, expectedStatusCode int) {
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil)
require.NoError(s.T(), err)
req.Host = host
resp, err := try.ResponseUntilStatusCode(req, 15*time.Second, expectedStatusCode)
require.NoError(s.T(), err)
resp.Body.Close()
}

View File

@@ -81,7 +81,7 @@ func (s *DockerSuite) TestDefaultDockerContainers() {
body, err := io.ReadAll(resp.Body)
require.NoError(s.T(), err)
var version map[string]interface{}
var version map[string]any
assert.NoError(s.T(), json.Unmarshal(body, &version))
assert.Equal(s.T(), "swarm/1.0.0", version["Version"])
@@ -145,7 +145,7 @@ func (s *DockerSuite) TestDockerContainersWithLabels() {
body, err := io.ReadAll(resp.Body)
require.NoError(s.T(), err)
var version map[string]interface{}
var version map[string]any
assert.NoError(s.T(), json.Unmarshal(body, &version))
assert.Equal(s.T(), "swarm/1.0.0", version["Version"])
@@ -203,7 +203,7 @@ func (s *DockerSuite) TestRestartDockerContainers() {
body, err := io.ReadAll(resp.Body)
require.NoError(s.T(), err)
var version map[string]interface{}
var version map[string]any
assert.NoError(s.T(), json.Unmarshal(body, &version))
assert.Equal(s.T(), "swarm/1.0.0", version["Version"])

View File

@@ -14,6 +14,7 @@ import (
// ErrorPagesSuite test suites.
type ErrorPagesSuite struct {
BaseSuite
ErrorPageIP string
BackendIP string
}

View File

@@ -24,6 +24,7 @@ import (
// etcd test suites.
type EtcdSuite struct {
BaseSuite
kvClient store.Store
etcdAddr string
}

View File

@@ -1273,6 +1273,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
ipStrategy:
@@ -1663,8 +1664,9 @@ spec:
description: |-
IPWhiteList defines the IPWhiteList middleware configuration.
This middleware accepts/refuses connections based on the client IP.
Deprecated: please use IPAllowList instead.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
sourceRange:
description: SourceRange defines the allowed IPs (or ranges of
@@ -1907,6 +1909,7 @@ spec:
description: |-
PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's.
It is enabled automatically when minVersion or maxVersion is set.
Deprecated: https://github.com/golang/go/issues/45430
type: boolean
sniStrict:
@@ -3703,6 +3706,7 @@ spec:
IPWhiteList holds the IP whitelist middleware configuration.
This middleware limits allowed requests based on the client IP.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
ipStrategy:
@@ -4093,8 +4097,9 @@ spec:
description: |-
IPWhiteList defines the IPWhiteList middleware configuration.
This middleware accepts/refuses connections based on the client IP.
Deprecated: please use IPAllowList instead.
More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/
Deprecated: please use IPAllowList instead.
properties:
sourceRange:
description: SourceRange defines the allowed IPs (or ranges of
@@ -4337,6 +4342,7 @@ spec:
description: |-
PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's.
It is enabled automatically when minVersion or maxVersion is set.
Deprecated: https://github.com/golang/go/issues/45430
type: boolean
sniStrict:

View File

@@ -8,12 +8,18 @@
[entryPoints]
[entryPoints.strict]
address = ":8000"
# Default: no encoded characters allowed
[entryPoints.strict.http.encodedCharacters]
allowEncodedSlash = false
[entryPoints.permissive]
address = ":8001"
# No config, default values should apply
[entryPoints.permissive2]
address = ":8002"
# No config for allowEncodedSlash, default value is effectively true
[entryPoints.permissive.http.encodedCharacters]
allowEncodedSlash = true
allowEncodedBackSlash = false
[api]
insecure = true

View File

@@ -8,8 +8,6 @@
[entryPoints]
[entryPoints.web]
address = ":8000"
[entryPoints.web.http.encodedCharacters]
allowEncodedSlash = true
[api]
insecure = true

View File

@@ -19,6 +19,7 @@ import (
// HealthCheck test suites.
type HealthCheckSuite struct {
BaseSuite
whoami1IP string
whoami2IP string
whoami3IP string
@@ -305,7 +306,7 @@ func (s *HealthCheckSuite) TestPropagate() {
require.NoError(s.T(), err)
}
try.Sleep(time.Second)
try.Sleep(time.Second) //nolint:staticcheck // Intentional use for integration test timing.
want2 := `IP: ` + s.whoami2IP
want4 := `IP: ` + s.whoami4IP
@@ -387,7 +388,7 @@ func (s *HealthCheckSuite) TestPropagate() {
require.NoError(s.T(), err)
}
try.Sleep(time.Second)
try.Sleep(time.Second) //nolint:staticcheck // Intentional use for integration test timing.
// Verify that everything is down, and that we get 503s everywhere.
for range 2 {
@@ -413,7 +414,7 @@ func (s *HealthCheckSuite) TestPropagate() {
require.NoError(s.T(), err)
}
try.Sleep(time.Second)
try.Sleep(time.Second) //nolint:staticcheck // Intentional use for integration test timing.
// Verify everything is up on root router.
reachedServers = make(map[string]int)

View File

@@ -187,7 +187,7 @@ func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) {
s.RegisterService(&_Greeter_serviceDesc, srv)
}
func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
func _Greeter_SayHello_Handler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
in := new(HelloRequest)
if err := dec(in); err != nil {
return nil, err
@@ -199,13 +199,13 @@ func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(in
Server: srv,
FullMethod: "/helloworld.Greeter/SayHello",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
handler := func(ctx context.Context, req any) (any, error) {
return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Greeter_StreamExample_Handler(srv interface{}, stream grpc.ServerStream) error {
func _Greeter_StreamExample_Handler(srv any, stream grpc.ServerStream) error {
m := new(StreamExampleRequest)
if err := stream.RecvMsg(m); err != nil {
return err

View File

@@ -876,40 +876,6 @@ func (s *HTTPSSuite) TestWithSNIDynamicConfigRouteWithTlsConfigurationDeletion()
require.NoError(s.T(), err)
}
// modifyCertificateConfFileContent replaces the content of a HTTPS configuration file.
func (s *HTTPSSuite) modifyCertificateConfFileContent(certFileName, confFileName string) {
file, err := os.OpenFile("./"+confFileName, os.O_WRONLY, os.ModeExclusive)
require.NoError(s.T(), err)
defer func() {
file.Close()
}()
err = file.Truncate(0)
require.NoError(s.T(), err)
// If certificate file is not provided, just truncate the configuration file
if len(certFileName) > 0 {
tlsConf := dynamic.Configuration{
TLS: &dynamic.TLSConfiguration{
Certificates: []*traefiktls.CertAndStores{
{
Certificate: traefiktls.Certificate{
CertFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".cert"),
KeyFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".key"),
},
},
},
},
}
var confBuffer bytes.Buffer
err := toml.NewEncoder(&confBuffer).Encode(tlsConf)
require.NoError(s.T(), err)
_, err = file.Write(confBuffer.Bytes())
require.NoError(s.T(), err)
}
}
func (s *HTTPSSuite) TestEntryPointHttpsRedirectAndPathModification() {
file := s.adaptFile("fixtures/https/https_redirect.toml", struct{}{})
s.traefikCmd(withConfigFile(file))
@@ -1176,6 +1142,40 @@ func (s *HTTPSSuite) TestWithInvalidTLSOption() {
}
}
// modifyCertificateConfFileContent replaces the content of a HTTPS configuration file.
func (s *HTTPSSuite) modifyCertificateConfFileContent(certFileName, confFileName string) {
file, err := os.OpenFile("./"+confFileName, os.O_WRONLY, os.ModeExclusive)
require.NoError(s.T(), err)
defer func() {
file.Close()
}()
err = file.Truncate(0)
require.NoError(s.T(), err)
// If certificate file is not provided, just truncate the configuration file
if len(certFileName) > 0 {
tlsConf := dynamic.Configuration{
TLS: &dynamic.TLSConfiguration{
Certificates: []*traefiktls.CertAndStores{
{
Certificate: traefiktls.Certificate{
CertFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".cert"),
KeyFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".key"),
},
},
},
},
}
var confBuffer bytes.Buffer
err := toml.NewEncoder(&confBuffer).Encode(tlsConf)
require.NoError(s.T(), err)
_, err = file.Write(confBuffer.Bytes())
require.NoError(s.T(), err)
}
}
func (s *SimpleSuite) TestMaxConcurrentStream() {
file := s.adaptFile("fixtures/https/max_concurrent_stream.toml", struct{}{})

View File

@@ -61,45 +61,12 @@ type composeDeploy struct {
type BaseSuite struct {
suite.Suite
containers map[string]testcontainers.Container
network *testcontainers.DockerNetwork
hostIP string
}
func (s *BaseSuite) waitForTraefik(containerName string) {
time.Sleep(1 * time.Second)
// Wait for Traefik to turn ready.
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/api/rawdata", nil)
require.NoError(s.T(), err)
err = try.Request(req, 2*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains(containerName))
require.NoError(s.T(), err)
}
func (s *BaseSuite) displayTraefikLogFile(path string) {
if s.T().Failed() {
if _, err := os.Stat(path); !os.IsNotExist(err) {
content, errRead := os.ReadFile(path)
// TODO TestName
// fmt.Printf("%s: Traefik logs: \n", c.TestName())
fmt.Print("Traefik logs: \n")
if errRead == nil {
fmt.Println(string(content))
} else {
fmt.Println(errRead)
}
} else {
// fmt.Printf("%s: No Traefik logs.\n", c.TestName())
fmt.Print("No Traefik logs.\n")
}
errRemove := os.Remove(path)
if errRemove != nil {
fmt.Println(errRemove)
}
}
}
func (s *BaseSuite) SetupSuite() {
if isDockerDesktop(context.Background(), s.T()) {
_, err := os.Stat(tailscaleSecretFilePath)
@@ -400,7 +367,7 @@ func (s *BaseSuite) displayTraefikLog(output *bytes.Buffer) {
if output == nil || output.Len() == 0 {
log.WithoutContext().Info("No Traefik logs.")
} else {
for _, line := range strings.Split(output.String(), "\n") {
for line := range strings.SplitSeq(output.String(), "\n") {
log.WithoutContext().Info(line)
}
}
@@ -416,7 +383,7 @@ func (s *BaseSuite) getDockerHost() string {
return dockerHost
}
func (s *BaseSuite) adaptFile(path string, tempObjects interface{}) string {
func (s *BaseSuite) adaptFile(path string, tempObjects any) string {
// Load file
tmpl, err := template.ParseFiles(path)
require.NoError(s.T(), err)
@@ -504,3 +471,37 @@ func (s *BaseSuite) composeExec(service string, args ...string) string {
return string(content)
}
func (s *BaseSuite) waitForTraefik(containerName string) {
time.Sleep(1 * time.Second)
// Wait for Traefik to turn ready.
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/api/rawdata", nil)
require.NoError(s.T(), err)
err = try.Request(req, 2*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains(containerName))
require.NoError(s.T(), err)
}
func (s *BaseSuite) displayTraefikLogFile(path string) {
if s.T().Failed() {
if _, err := os.Stat(path); !os.IsNotExist(err) {
content, errRead := os.ReadFile(path)
// TODO TestName
// fmt.Printf("%s: Traefik logs: \n", c.TestName())
fmt.Print("Traefik logs: \n")
if errRead == nil {
fmt.Println(string(content))
} else {
fmt.Println(errRead)
}
} else {
// fmt.Printf("%s: No Traefik logs.\n", c.TestName())
fmt.Print("No Traefik logs.\n")
}
errRemove := os.Remove(path)
if errRemove != nil {
fmt.Println(errRemove)
}
}
}

View File

@@ -1,5 +1,4 @@
//go:build !windows
// +build !windows
package integration

View File

@@ -14,6 +14,7 @@ import (
// Marathon test suites.
type MarathonSuite15 struct {
BaseSuite
marathonURL string
}

View File

@@ -16,6 +16,7 @@ const containerNameMarathon = "marathon"
// Marathon test suites.
type MarathonSuite struct {
BaseSuite
marathonURL string
}

View File

@@ -3,6 +3,7 @@ package integration
import (
"bufio"
"net"
"strings"
"testing"
"time"
@@ -15,6 +16,7 @@ import (
type ProxyProtocolSuite struct {
BaseSuite
whoamiIP string
}
@@ -124,15 +126,16 @@ func proxyProtoRequest(address string, version byte) (string, error) {
}
// Read the response from the server
var content string
var content strings.Builder
scanner := bufio.NewScanner(conn)
for scanner.Scan() {
content += scanner.Text() + "\n"
content.WriteString(scanner.Text())
content.WriteString("\n")
}
if scanner.Err() != nil {
return "", err
}
return content, nil
return content.String(), nil
}

View File

@@ -12,6 +12,7 @@ import (
type RateLimitSuite struct {
BaseSuite
ServerIP string
}

View File

@@ -29,6 +29,7 @@ import (
// Redis test suites.
type RedisSentinelSuite struct {
BaseSuite
kvClient store.Store
redisEndpoints []string
}
@@ -76,36 +77,6 @@ func (s *RedisSentinelSuite) TearDownSuite() {
}
}
func (s *RedisSentinelSuite) setupSentinelConfiguration(ports []string) {
for i, port := range ports {
templateValue := struct{ SentinelPort string }{SentinelPort: port}
// Load file
templateFile := "resources/compose/config/sentinel_template.conf"
tmpl, err := template.ParseFiles(templateFile)
require.NoError(s.T(), err)
folder, prefix := filepath.Split(templateFile)
fileName := fmt.Sprintf("%s/sentinel%d.conf", folder, i+1)
tmpFile, err := os.Create(fileName)
require.NoError(s.T(), err)
defer tmpFile.Close()
err = tmpFile.Chmod(0o666)
require.NoError(s.T(), err)
model := structs.Map(templateValue)
model["SelfFilename"] = tmpFile.Name()
err = tmpl.ExecuteTemplate(tmpFile, prefix, model)
require.NoError(s.T(), err)
err = tmpFile.Sync()
require.NoError(s.T(), err)
}
}
func (s *RedisSentinelSuite) TestSentinelConfiguration() {
file := s.adaptFile("fixtures/redis/sentinel.toml", struct{ RedisAddress string }{
RedisAddress: strings.Join(s.redisEndpoints, `","`),
@@ -202,3 +173,33 @@ func (s *RedisSentinelSuite) TestSentinelConfiguration() {
log.WithoutContext().Info(text)
}
}
func (s *RedisSentinelSuite) setupSentinelConfiguration(ports []string) {
for i, port := range ports {
templateValue := struct{ SentinelPort string }{SentinelPort: port}
// Load file
templateFile := "resources/compose/config/sentinel_template.conf"
tmpl, err := template.ParseFiles(templateFile)
require.NoError(s.T(), err)
folder, prefix := filepath.Split(templateFile)
fileName := fmt.Sprintf("%s/sentinel%d.conf", folder, i+1)
tmpFile, err := os.Create(fileName)
require.NoError(s.T(), err)
defer tmpFile.Close()
err = tmpFile.Chmod(0o666)
require.NoError(s.T(), err)
model := structs.Map(templateValue)
model["SelfFilename"] = tmpFile.Name()
err = tmpl.ExecuteTemplate(tmpFile, prefix, model)
require.NoError(s.T(), err)
err = tmpFile.Sync()
require.NoError(s.T(), err)
}
}

View File

@@ -25,6 +25,7 @@ import (
// Redis test suites.
type RedisSuite struct {
BaseSuite
kvClient store.Store
redisEndpoints []string
}

View File

@@ -18,6 +18,7 @@ import (
type RestSuite struct {
BaseSuite
whoamiAddr string
}

View File

@@ -15,6 +15,7 @@ import (
type RetrySuite struct {
BaseSuite
whoamiIP string
}

View File

@@ -1520,6 +1520,12 @@ func (s *SimpleSuite) TestEncodedCharactersDifferentEntryPoints() {
target: "127.0.0.1:8001", // permissive entry point
expected: http.StatusOK,
},
{
desc: "Encoded slash should be ALLOWED on permissive2 entry point",
request: "GET /path%2Fwith%2Fslash HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
target: "127.0.0.1:8002", // permissive2 entry point
expected: http.StatusOK,
},
{
desc: "Regular path should work on strict entry point",
request: "GET /regular/path HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
@@ -1532,6 +1538,12 @@ func (s *SimpleSuite) TestEncodedCharactersDifferentEntryPoints() {
target: "127.0.0.1:8001",
expected: http.StatusOK,
},
{
desc: "Regular path should work on permissive2 entry point",
request: "GET /regular/path HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
target: "127.0.0.1:8002",
expected: http.StatusOK,
},
}
for _, test := range testCases {

View File

@@ -12,6 +12,7 @@ import (
type TracingSuite struct {
BaseSuite
whoamiIP string
whoamiPort int
tracerZipkinIP string
@@ -43,15 +44,6 @@ func (s *TracingSuite) TearDownSuite() {
s.BaseSuite.TearDownSuite()
}
func (s *TracingSuite) startZipkin() {
s.composeUp("zipkin")
s.tracerZipkinIP = s.getComposeServiceIP("zipkin")
// Wait for Zipkin to turn ready.
err := try.GetRequest("http://"+s.tracerZipkinIP+":9411/api/v2/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
require.NoError(s.T(), err)
}
func (s *TracingSuite) TestZipkinRateLimit() {
s.startZipkin()
@@ -141,15 +133,6 @@ func (s *TracingSuite) TestZipkinAuth() {
require.NoError(s.T(), err)
}
func (s *TracingSuite) startJaeger() {
s.composeUp("jaeger", "whoami")
s.tracerJaegerIP = s.getComposeServiceIP("jaeger")
// Wait for Jaeger to turn ready.
err := try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
require.NoError(s.T(), err)
}
func (s *TracingSuite) TestJaegerRateLimit() {
s.startJaeger()
// defer s.composeStop(c, "jaeger")
@@ -290,3 +273,21 @@ func (s *TracingSuite) TestJaegerAuthCollector() {
err = try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file"))
require.NoError(s.T(), err)
}
func (s *TracingSuite) startZipkin() {
s.composeUp("zipkin")
s.tracerZipkinIP = s.getComposeServiceIP("zipkin")
// Wait for Zipkin to turn ready.
err := try.GetRequest("http://"+s.tracerZipkinIP+":9411/api/v2/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
require.NoError(s.T(), err)
}
func (s *TracingSuite) startJaeger() {
s.composeUp("jaeger", "whoami")
s.tracerJaegerIP = s.getComposeServiceIP("jaeger")
// Wait for Jaeger to turn ready.
err := try.GetRequest("http://"+s.tracerJaegerIP+":16686/api/services", 20*time.Second, try.StatusCodeIs(http.StatusOK))
require.NoError(s.T(), err)
}

View File

@@ -19,6 +19,7 @@ const (
type timedAction func(timeout time.Duration, operation DoCondition) error
// Sleep pauses the current goroutine for at least the duration d.
//
// Deprecated: Use only when use another Try[...] functions is not possible.
func Sleep(d time.Duration) {
d = applyCIMultiplier(d)
@@ -92,10 +93,7 @@ func Do(timeout time.Duration, operation DoCondition) error {
panic("timeout must be larger than zero")
}
interval := time.Duration(math.Ceil(float64(timeout) / 15.0))
if interval > maxInterval {
interval = maxInterval
}
interval := min(time.Duration(math.Ceil(float64(timeout)/15.0)), maxInterval)
timeout = applyCIMultiplier(timeout)
@@ -166,7 +164,7 @@ func doRequest(action timedAction, timeout time.Duration, request *http.Request,
func applyCIMultiplier(timeout time.Duration) time.Duration {
ci := os.Getenv("CI")
if len(ci) > 0 {
log.Debug("Apply CI multiplier:", CITimeoutMultiplier)
log.WithoutContext().Debug("Apply CI multiplier:", CITimeoutMultiplier)
return time.Duration(float64(timeout) * CITimeoutMultiplier)
}
return timeout

View File

@@ -25,6 +25,7 @@ import (
// Zk test suites.
type ZookeeperSuite struct {
BaseSuite
kvClient store.Store
zookeeperAddr string
}

View File

@@ -78,7 +78,7 @@ func main() {
logger.Fatal(err)
}
genStaticConfDoc("./docs/content/reference/static-configuration/env-ref.md", "", func(i interface{}) ([]parser.Flat, error) {
genStaticConfDoc("./docs/content/reference/static-configuration/env-ref.md", "", func(i any) ([]parser.Flat, error) {
return env.Encode(env.DefaultNamePrefix, i)
})
genStaticConfDoc("./docs/content/reference/static-configuration/cli-ref.md", "--", flag.Encode)
@@ -240,7 +240,7 @@ func clean(element any) {
valSvcs.SetMapIndex(reflect.ValueOf(fmt.Sprintf("%s1", valueSvcRoot.Type().Name())), reflect.Value{})
}
func genStaticConfDoc(outputFile, prefix string, encodeFn func(interface{}) ([]parser.Flat, error)) {
func genStaticConfDoc(outputFile, prefix string, encodeFn func(any) ([]parser.Flat, error)) {
logger := log.WithoutContext().WithField("file", outputFile)
element := &cmd.NewTraefikConfiguration().Configuration
@@ -309,7 +309,7 @@ type errWriter struct {
err error
}
func (ew *errWriter) writeln(a ...interface{}) {
func (ew *errWriter) writeln(a ...any) {
if ew.err != nil {
return
}
@@ -319,15 +319,15 @@ func (ew *errWriter) writeln(a ...interface{}) {
func genKVDynConfDoc(outputFile string) {
dynConfPath := "./docs/content/reference/dynamic-configuration/file.toml"
conf := map[string]interface{}{}
conf := map[string]any{}
_, err := toml.DecodeFile(dynConfPath, &conf)
if err != nil {
log.Fatal(err)
log.WithoutContext().Fatal(err)
}
file, err := os.Create(outputFile)
if err != nil {
log.Fatal(err)
log.WithoutContext().Fatal(err)
}
store := storeWriter{data: map[string]string{}}
@@ -335,7 +335,7 @@ func genKVDynConfDoc(outputFile string) {
c := client{store: store}
err = c.load("traefik", conf)
if err != nil {
log.Fatal(err)
log.WithoutContext().Fatal(err)
}
var keys []string
@@ -374,10 +374,10 @@ type client struct {
store storeWriter
}
func (c client) load(parentKey string, conf map[string]interface{}) error {
func (c client) load(parentKey string, conf map[string]any) error {
for k, v := range conf {
switch entry := v.(type) {
case map[string]interface{}:
case map[string]any:
key := path.Join(parentKey, k)
if len(entry) == 0 {
@@ -391,7 +391,7 @@ func (c client) load(parentKey string, conf map[string]interface{}) error {
return err
}
}
case []map[string]interface{}:
case []map[string]any:
for i, o := range entry {
key := path.Join(parentKey, k, strconv.Itoa(i))
@@ -399,11 +399,11 @@ func (c client) load(parentKey string, conf map[string]interface{}) error {
return err
}
}
case []interface{}:
case []any:
for i, o := range entry {
key := path.Join(parentKey, k, strconv.Itoa(i))
err := c.store.Put(key, []byte(fmt.Sprintf("%v", o)), nil)
err := c.store.Put(key, fmt.Appendf(nil, "%v", o), nil)
if err != nil {
return err
}
@@ -411,7 +411,7 @@ func (c client) load(parentKey string, conf map[string]interface{}) error {
default:
key := path.Join(parentKey, k)
err := c.store.Put(key, []byte(fmt.Sprintf("%v", v)), nil)
err := c.store.Put(key, fmt.Appendf(nil, "%v", v), nil)
if err != nil {
return err
}

View File

@@ -38,7 +38,7 @@ func encodeNode(labels map[string]string, root string, node *parser.Node) {
}
}
func encodeRawValue(labels map[string]string, root string, rawValue interface{}) {
func encodeRawValue(labels map[string]string, root string, rawValue any) {
if rawValue == nil {
return
}
@@ -47,14 +47,14 @@ func encodeRawValue(labels map[string]string, root string, rawValue interface{})
if tValue.Kind() == reflect.Map && tValue.Elem().Kind() == reflect.Interface {
r := reflect.ValueOf(rawValue).
Convert(reflect.TypeOf((map[string]interface{})(nil))).
Interface().(map[string]interface{})
Convert(reflect.TypeFor[map[string]any]()).
Interface().(map[string]any)
for k, v := range r {
switch tv := v.(type) {
case string:
labels[root+"."+k] = tv
case []interface{}:
case []any:
for i, e := range tv {
encodeRawValue(labels, fmt.Sprintf("%s.%s[%d]", root, k, i), e)
}

View File

@@ -72,10 +72,7 @@ func pagination(request *http.Request, maximum int) (pageInfo, error) {
return pageInfo{}, fmt.Errorf("invalid request: page: %d, per_page: %d", page, perPage)
}
endIndex := startIndex + perPage
if endIndex >= maximum {
endIndex = maximum
}
endIndex := min(startIndex+perPage, maximum)
nextPage := 1
if page*perPage < maximum {

View File

@@ -15,7 +15,7 @@ func init() {
expvar.Publish("Goroutines2", expvar.Func(goroutines))
}
func goroutines() interface{} {
func goroutines() any {
return runtime.NumGoroutine()
}

View File

@@ -30,6 +30,7 @@ func writeError(rw http.ResponseWriter, msg string, code int) {
type serviceInfoRepresentation struct {
*runtime.ServiceInfo
ServerStatus map[string]string `json:"serverStatus,omitempty"`
}
@@ -147,12 +148,12 @@ func getProviderName(id string) string {
return strings.SplitN(id, "@", 2)[1]
}
func extractType(element interface{}) string {
func extractType(element any) string {
v := reflect.ValueOf(element).Elem()
for i := range v.NumField() {
field := v.Field(i)
if field.Kind() == reflect.Map && field.Type().Elem() == reflect.TypeOf(dynamic.PluginConf{}) {
if field.Kind() == reflect.Map && field.Type().Elem() == reflect.TypeFor[dynamic.PluginConf]() {
if keys := field.MapKeys(); len(keys) == 1 {
return keys[0].String()
}

View File

@@ -15,6 +15,7 @@ import (
type entryPointRepresentation struct {
*static.EntryPoint
Name string `json:"name,omitempty"`
}

View File

@@ -235,7 +235,7 @@ func TestHandler_EntryPoints(t *testing.T) {
require.NoError(t, err)
if *updateExpected {
var results interface{}
var results any
err := json.Unmarshal(contents, &results)
require.NoError(t, err)

View File

@@ -17,6 +17,7 @@ import (
type routerRepresentation struct {
*runtime.RouterInfo
Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"`
}
@@ -35,6 +36,7 @@ func newRouterRepresentation(name string, rt *runtime.RouterInfo) routerRepresen
type serviceRepresentation struct {
*runtime.ServiceInfo
ServerStatus map[string]string `json:"serverStatus,omitempty"`
Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"`
@@ -53,6 +55,7 @@ func newServiceRepresentation(name string, si *runtime.ServiceInfo) serviceRepre
type middlewareRepresentation struct {
*runtime.MiddlewareInfo
Name string `json:"name,omitempty"`
Provider string `json:"provider,omitempty"`
Type string `json:"type,omitempty"`

Some files were not shown because too many files have changed in this diff Show More