Merge branch 'v3.0' of github.com:traefik/traefik

Signed-off-by: baalajimaestro <me@baalajimaestro.me>
This commit is contained in:
baalajimaestro 2024-01-19 12:30:00 +05:30
commit d69e3d80af
Signed by: baalajimaestro
GPG key ID: F93C394FE9BBAFD5
65 changed files with 1978 additions and 1036 deletions

View file

@ -1,5 +1,5 @@
dist/ dist/
!dist/traefik !dist/**/traefik
site/ site/
vendor/ vendor/
.idea/ .idea/

View file

@ -1,6 +1,13 @@
FROM scratch # syntax=docker/dockerfile:1.2
COPY script/ca-certificates.crt /etc/ssl/certs/ FROM alpine:3.19
COPY dist/traefik /
RUN apk --no-cache --no-progress add ca-certificates tzdata \
&& rm -rf /var/cache/apk/*
ARG TARGETPLATFORM
COPY ./dist/$TARGETPLATFORM/traefik /
EXPOSE 80 EXPOSE 80
VOLUME ["/tmp"] VOLUME ["/tmp"]
ENTRYPOINT ["/traefik"] ENTRYPOINT ["/traefik"]

138
Makefile
View file

@ -7,8 +7,22 @@ VERSION := $(if $(VERSION),$(VERSION),$(VERSION_GIT))
GIT_BRANCH := $(subst heads/,,$(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)) GIT_BRANCH := $(subst heads/,,$(shell git rev-parse --abbrev-ref HEAD 2>/dev/null))
REPONAME := $(shell echo $(REPO) | tr '[:upper:]' '[:lower:]')
BIN_NAME := traefik
CODENAME := cheddar
DATE := $(shell date -u '+%Y-%m-%d_%I:%M:%S%p')
# Default build target
GOOS := $(shell go env GOOS)
GOARCH := $(shell go env GOARCH)
LINT_EXECUTABLES = misspell shellcheck
DOCKER_BUILD_PLATFORMS ?= linux/amd64,linux/arm64
.PHONY: default .PHONY: default
default: binary default: generate binary
## Create the "dist" directory ## Create the "dist" directory
dist: dist:
@ -35,43 +49,57 @@ webui/static/index.html:
.PHONY: generate-webui .PHONY: generate-webui
generate-webui: webui/static/index.html generate-webui: webui/static/index.html
## Generate code
.PHONY: generate
generate:
go generate
## Build the binary ## Build the binary
.PHONY: binary .PHONY: binary
binary: generate-webui binary: generate-webui dist
./script/make.sh generate binary @echo SHA: $(VERSION) $(CODENAME) $(DATE)
CGO_ENABLED=0 GOGC=off 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)" \
-installsuffix nocgo -o "./dist/${GOOS}/${GOARCH}/$(BIN_NAME)" ./cmd/traefik
## Build the linux binary locally binary-linux-arm64: export GOOS := linux
.PHONY: binary-debug binary-linux-arm64: export GOARCH := arm64
binary-debug: generate-webui binary-linux-arm64:
GOOS=linux ./script/make.sh binary @$(MAKE) binary
binary-linux-amd64: export GOOS := linux
binary-linux-amd64: export GOARCH := amd64
binary-linux-amd64:
@$(MAKE) binary
binary-windows-amd64: export GOOS := windows
binary-windows-amd64: export GOARCH := amd64
binary-windows-amd64: export BIN_NAME := traefik.exe
binary-windows-amd64:
@$(MAKE) binary
## Build the binary for the standard platforms (linux, darwin, windows) ## Build the binary for the standard platforms (linux, darwin, windows)
.PHONY: crossbinary-default .PHONY: crossbinary-default
crossbinary-default: generate-webui crossbinary-default: generate generate-webui
./script/make.sh generate crossbinary-default $(CURDIR)/script/crossbinary-default.sh
## Build the binary for the standard platforms (linux, darwin, windows) in parallel
.PHONY: crossbinary-default-parallel
crossbinary-default-parallel:
$(MAKE) generate-webui
$(MAKE) crossbinary-default
## Run the unit and integration tests ## Run the unit and integration tests
.PHONY: test .PHONY: test
test: test: test-unit test-integration
./script/make.sh generate test-unit binary test-integration
## Run the unit tests ## Run the unit tests
.PHONY: test-unit .PHONY: test-unit
test-unit: test-unit:
./script/make.sh generate test-unit GOOS=$(GOOS) GOARCH=$(GOARCH) go test -cover "-coverprofile=cover.out" -v $(TESTFLAGS) ./pkg/... ./cmd/...
## Run the integration tests ## Run the integration tests
.PHONY: test-integration .PHONY: test-integration
test-integration: test-integration: binary
./script/make.sh generate binary test-integration GOOS=$(GOOS) GOARCH=$(GOARCH) go test ./integration -test.timeout=20m -failfast -v $(TESTFLAGS)
## Pull all images for integration tests ## Pull all Docker images to avoid timeout during integration tests
.PHONY: pull-images .PHONY: pull-images
pull-images: pull-images:
grep --no-filename -E '^\s+image:' ./integration/resources/compose/*.yml \ grep --no-filename -E '^\s+image:' ./integration/resources/compose/*.yml \
@ -80,38 +108,47 @@ pull-images:
| uniq \ | uniq \
| xargs -P 6 -n 1 docker pull | xargs -P 6 -n 1 docker pull
EXECUTABLES = misspell shellcheck ## Lint run golangci-lint
.PHONY: lint
lint:
golangci-lint run
## Validate code and docs ## Validate code and docs
.PHONY: validate-files .PHONY: validate-files
validate-files: validate-files: lint
$(foreach exec,$(EXECUTABLES),\ $(foreach exec,$(LINT_EXECUTABLES),\
$(if $(shell which $(exec)),,$(error "No $(exec) in PATH"))) $(if $(shell which $(exec)),,$(error "No $(exec) in PATH")))
./script/make.sh generate validate-lint validate-misspell $(CURDIR)/script/validate-misspell.sh
bash $(CURDIR)/script/validate-shell-script.sh $(CURDIR)/script/validate-shell-script.sh
## Validate code, docs, and vendor ## Validate code, docs, and vendor
.PHONY: validate .PHONY: validate
validate: validate: lint
$(foreach exec,$(EXECUTABLES),\ $(foreach exec,$(EXECUTABLES),\
$(if $(shell which $(exec)),,$(error "No $(exec) in PATH"))) $(if $(shell which $(exec)),,$(error "No $(exec) in PATH")))
./script/make.sh generate validate-lint validate-misspell validate-vendor $(CURDIR)/script/validate-vendor.sh
bash $(CURDIR)/script/validate-shell-script.sh $(CURDIR)/script/validate-misspell.sh
$(CURDIR)/script/validate-shell-script.sh
# Target for building images for multiple architectures.
.PHONY: multi-arch-image-%
multi-arch-image-%: binary-linux-amd64 binary-linux-arm64
docker buildx build $(DOCKER_BUILDX_ARGS) -t traefik/traefik:$* --platform=$(DOCKER_BUILD_PLATFORMS) -f Dockerfile .
## Clean up static directory and build a Docker Traefik image ## Clean up static directory and build a Docker Traefik image
.PHONY: build-image .PHONY: build-image
build-image: clean-webui binary build-image: export DOCKER_BUILDX_ARGS := --load
docker build -t $(TRAEFIK_IMAGE) . build-image: export DOCKER_BUILD_PLATFORMS := linux/$(GOARCH)
build-image: clean-webui
@$(MAKE) multi-arch-image-latest
## Build a Docker Traefik image without re-building the webui ## Build a Docker Traefik image without re-building the webui when it's already built
.PHONY: build-image-dirty .PHONY: build-image-dirty
build-image-dirty: binary build-image-dirty: export DOCKER_BUILDX_ARGS := --load
docker build -t $(TRAEFIK_IMAGE) . build-image-dirty: export DOCKER_BUILD_PLATFORMS := linux/$(GOARCH)
build-image-dirty:
## Locally build traefik for linux, then shove it an alpine image, with basic tools. @$(MAKE) multi-arch-image-latest
.PHONY: build-image-debug
build-image-debug: binary-debug
docker build -t $(TRAEFIK_IMAGE) -f debug.Dockerfile .
## Build documentation site ## Build documentation site
.PHONY: docs .PHONY: docs
@ -141,30 +178,9 @@ generate-genconf:
## Create packages for the release ## Create packages for the release
.PHONY: release-packages .PHONY: release-packages
release-packages: generate-webui release-packages: generate-webui
rm -rf dist $(CURDIR)/script/release-packages.sh
@- $(foreach os, linux darwin windows freebsd openbsd, \
goreleaser release --skip-publish -p 2 --timeout="90m" --config $(shell go run ./internal/release $(os)); \
go clean -cache; \
)
cat dist/**/*_checksums.txt >> dist/traefik_${VERSION}_checksums.txt
rm dist/**/*_checksums.txt
tar cfz dist/traefik-${VERSION}.src.tar.gz \
--exclude-vcs \
--exclude .idea \
--exclude .travis \
--exclude .semaphoreci \
--exclude .github \
--exclude dist .
chown -R $(shell id -u):$(shell id -g) dist/
## Format the Code ## Format the Code
.PHONY: fmt .PHONY: fmt
fmt: fmt:
gofmt -s -l -w $(SRCS) gofmt -s -l -w $(SRCS)
.PHONY: run-dev
run-dev:
go generate
GO111MODULE=on go build ./cmd/traefik
./traefik

View file

@ -1,37 +0,0 @@
FROM golang:1.21-alpine
RUN apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \
&& update-ca-certificates \
&& rm -rf /var/cache/apk/*
# Which docker version to test on
ARG DOCKER_VERSION=18.09.7
# Download docker
RUN mkdir -p /usr/local/bin \
&& curl -fL https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz \
| tar -xzC /usr/local/bin --transform 's#^.+/##x'
# Download golangci-lint binary to bin folder in $GOPATH
RUN curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- -b $GOPATH/bin v1.55.2
# Download misspell binary to bin folder in $GOPATH
RUN curl -sfL https://raw.githubusercontent.com/golangci/misspell/master/install-misspell.sh | bash -s -- -b $GOPATH/bin v0.4.0
# Download goreleaser binary to bin folder in $GOPATH
RUN curl -sfL https://gist.githubusercontent.com/traefiker/6d7ac019c11d011e4f131bb2cca8900e/raw/goreleaser.sh | sh
WORKDIR /go/src/github.com/traefik/traefik
# Because of CVE-2022-24765 (https://github.blog/2022-04-12-git-security-vulnerability-announced/),
# we configure git to allow the Traefik codebase path on the Host for docker in docker usages.
ARG HOST_PWD=""
RUN git config --global --add safe.directory "${HOST_PWD}"
# Download go modules
COPY go.mod .
COPY go.sum .
RUN GO111MODULE=on GOPROXY=https://proxy.golang.org go mod download
COPY . /go/src/github.com/traefik/traefik

View file

@ -1,10 +0,0 @@
FROM alpine:3.14
# Feel free to add below any helpful dependency for debugging.
# iproute2 is for ss.
RUN apk --no-cache --no-progress add bash curl ca-certificates tzdata lsof iproute2 \
&& update-ca-certificates \
&& rm -rf /var/cache/apk/*
COPY dist/traefik /
EXPOSE 80
VOLUME ["/tmp"]
ENTRYPOINT ["/traefik"]

View file

@ -58,10 +58,12 @@ Once you've set up your go environment and cloned the source repository, you can
```bash ```bash
$ make binary $ make binary
./script/make.sh generate binary SHA: 8fddfe118288bb5280eb5e77fa952f52def360b4 cheddar 2024-01-11_03:14:57PM
---> Making bundle: generate (in .) CGO_ENABLED=0 GOGC=off GOOS=darwin GOARCH=arm64 go build -ldflags "-s -w \
-X github.com/traefik/traefik/v2/pkg/version.Version=8fddfe118288bb5280eb5e77fa952f52def360b4 \
---> Making bundle: binary (in .) -X github.com/traefik/traefik/v2/pkg/version.Codename=cheddar \
-X github.com/traefik/traefik/v2/pkg/version.BuildDate=2024-01-11_03:14:57PM" \
-installsuffix nocgo -o "./dist/darwin/arm64/traefik" ./cmd/traefik
$ ls dist/ $ ls dist/
traefik* traefik*
@ -77,10 +79,7 @@ Run all tests (unit and integration) using the `test` target.
```bash ```bash
$ make test-unit $ make test-unit
./script/make.sh generate test-unit GOOS=darwin GOARCH=arm64 go test -cover "-coverprofile=cover.out" -v ./pkg/... ./cmd/...
---> Making bundle: generate (in .)
---> Making bundle: test-unit (in .)
+ go test -cover -coverprofile=cover.out . + go test -cover -coverprofile=cover.out .
ok github.com/traefik/traefik 0.005s coverage: 4.1% of statements ok github.com/traefik/traefik 0.005s coverage: 4.1% of statements

View file

@ -25,7 +25,7 @@ The main features include dynamic configuration, automatic service discovery, an
## Edge Router ## Edge Router
Traefik is an *Edge Router*, it means that it's the door to your platform, and that it intercepts and routes every incoming request: Traefik is an *Edge Router*; this means that it's the door to your platform, and that it intercepts and routes every incoming request:
it knows all the logic and every [rule](../routing/routers/index.md#rule "Link to docs about routing rules") that determine which services handle which requests (based on the *path*, the *host*, *headers*, etc.). it knows all the logic and every [rule](../routing/routers/index.md#rule "Link to docs about routing rules") that determine which services handle which requests (based on the *path*, the *host*, *headers*, etc.).
![The Door to Your Infrastructure](../assets/img/traefik-concepts-1.png "Picture explaining the infrastructure") ![The Door to Your Infrastructure](../assets/img/traefik-concepts-1.png "Picture explaining the infrastructure")
@ -38,7 +38,7 @@ Deploying your services, you attach information that tells Traefik the character
![Decentralized Configuration](../assets/img/traefik-concepts-2.png "Picture about Decentralized Configuration") ![Decentralized Configuration](../assets/img/traefik-concepts-2.png "Picture about Decentralized Configuration")
It means that when a service is deployed, Traefik detects it immediately and updates the routing rules in real time. This means that when a service is deployed, Traefik detects it immediately and updates the routing rules in real time.
Similarly, when a service is removed from the infrastructure, the corresponding route is deleted accordingly. Similarly, when a service is removed from the infrastructure, the corresponding route is deleted accordingly.
You no longer need to create and synchronize configuration files cluttered with IP addresses or other rules. You no longer need to create and synchronize configuration files cluttered with IP addresses or other rules.

View file

@ -55,10 +55,10 @@ http:
Responses are compressed when the following criteria are all met: Responses are compressed when the following criteria are all met:
* The `Accept-Encoding` request header contains `gzip`, `*`, and/or `br` with or without [quality values](https://developer.mozilla.org/en-US/docs/Glossary/Quality_values). * The `Accept-Encoding` request header contains `gzip`, `*`, and/or `br` with or without [quality values](https://developer.mozilla.org/en-US/docs/Glossary/Quality_values).
If the `Accept-Encoding` request header is absent, it is meant as br compression is requested. If the `Accept-Encoding` request header is absent, the response won't be encoded.
If it is present, but its value is the empty string, then compression is disabled. If it is present, but its value is the empty string, then compression is disabled.
* The response is not already compressed, i.e. the `Content-Encoding` response header is not already set. * The response is not already compressed, i.e. the `Content-Encoding` response header is not already set.
* The response`Content-Type` header is not one among the [excludedContentTypes options](#excludedcontenttypes). * The response`Content-Type` header is not one among the [excludedContentTypes options](#excludedcontenttypes), or is one among the [includedContentTypes options](#includedcontenttypes).
* The response body is larger than the [configured minimum amount of bytes](#minresponsebodybytes) (default is `1024`). * The response body is larger than the [configured minimum amount of bytes](#minresponsebodybytes) (default is `1024`).
## Configuration Options ## Configuration Options
@ -73,6 +73,10 @@ The responses with content types defined in `excludedContentTypes` are not compr
Content types are compared in a case-insensitive, whitespace-ignored manner. Content types are compared in a case-insensitive, whitespace-ignored manner.
!!! info
The `excludedContentTypes` and `includedContentTypes` options are mutually exclusive.
!!! info "In the case of gzip" !!! info "In the case of gzip"
If the `Content-Type` header is not defined, or empty, the compress middleware will automatically [detect](https://mimesniff.spec.whatwg.org/) a content type. If the `Content-Type` header is not defined, or empty, the compress middleware will automatically [detect](https://mimesniff.spec.whatwg.org/) a content type.
@ -117,6 +121,59 @@ http:
excludedContentTypes = ["text/event-stream"] excludedContentTypes = ["text/event-stream"]
``` ```
### `includedContentTypes`
_Optional, Default=""_
`includedContentTypes` specifies a list of content types to compare the `Content-Type` header of the responses before compressing.
The responses with content types defined in `includedContentTypes` are compressed.
Content types are compared in a case-insensitive, whitespace-ignored manner.
!!! info
The `excludedContentTypes` and `includedContentTypes` options are mutually exclusive.
```yaml tab="Docker & Swarm"
labels:
- "traefik.http.middlewares.test-compress.compress.includedcontenttypes=application/json,text/html,text/plain"
```
```yaml tab="Kubernetes"
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: test-compress
spec:
compress:
includedContentTypes:
- application/json
- text/html
- text/plain
```
```yaml tab="Consul Catalog"
- "traefik.http.middlewares.test-compress.compress.includedcontenttypes=application/json,text/html,text/plain"
```
```yaml tab="File (YAML)"
http:
middlewares:
test-compress:
compress:
includedContentTypes:
- application/json
- text/html
- text/plain
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-compress.compress]
includedContentTypes = ["application/json","text/html","text/plain"]
```
### `minResponseBodyBytes` ### `minResponseBodyBytes`
_Optional, Default=1024_ _Optional, Default=1024_

View file

@ -285,6 +285,55 @@ http:
authRequestHeaders = "Accept,X-CustomHeader" authRequestHeaders = "Accept,X-CustomHeader"
``` ```
### `addAuthCookiesToResponse`
The `addAuthCookiesToResponse` option is the list of cookies to copy from the authentication server to the response,
replacing any existing conflicting cookie from the forwarded response.
!!! info
Please note that all backend cookies matching the configured list will not be added to the response.
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.addAuthCookiesToResponse=Session-Cookie,State-Cookie"
```
```yaml tab="Kubernetes"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
forwardAuth:
address: https://example.com/auth
addAuthCookiesToResponse:
- Session-Cookie
- State-Cookie
```
```yaml tab="Consul Catalog"
- "traefik.http.middlewares.test-auth.forwardauth.addAuthCookiesToResponse=Session-Cookie,State-Cookie"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-auth.forwardAuth]
address = "https://example.com/auth"
addAuthCookiesToResponse = ["Session-Cookie", "State-Cookie"]
```
```yaml tab="File (YAML)"
http:
middlewares:
test-auth:
forwardAuth:
address: "https://example.com/auth"
addAuthCookiesToResponse:
- "Session-Cookie"
- "State-Cookie"
```
### `tls` ### `tls`
_Optional_ _Optional_

View file

@ -1,124 +1,133 @@
- "traefik.http.middlewares.middleware00.addprefix.prefix=foobar" ## CODE GENERATED AUTOMATICALLY
- "traefik.http.middlewares.middleware01.basicauth.headerfield=foobar" ## THIS FILE MUST NOT BE EDITED BY HAND
- "traefik.http.middlewares.middleware01.basicauth.realm=foobar" - "traefik.http.middlewares.middleware01.addprefix.prefix=foobar"
- "traefik.http.middlewares.middleware01.basicauth.removeheader=true" - "traefik.http.middlewares.middleware02.basicauth.headerfield=foobar"
- "traefik.http.middlewares.middleware01.basicauth.users=foobar, foobar" - "traefik.http.middlewares.middleware02.basicauth.realm=foobar"
- "traefik.http.middlewares.middleware01.basicauth.usersfile=foobar" - "traefik.http.middlewares.middleware02.basicauth.removeheader=true"
- "traefik.http.middlewares.middleware02.buffering.maxrequestbodybytes=42" - "traefik.http.middlewares.middleware02.basicauth.users=foobar, foobar"
- "traefik.http.middlewares.middleware02.buffering.maxresponsebodybytes=42" - "traefik.http.middlewares.middleware02.basicauth.usersfile=foobar"
- "traefik.http.middlewares.middleware02.buffering.memrequestbodybytes=42" - "traefik.http.middlewares.middleware03.buffering.maxrequestbodybytes=42"
- "traefik.http.middlewares.middleware02.buffering.memresponsebodybytes=42" - "traefik.http.middlewares.middleware03.buffering.maxresponsebodybytes=42"
- "traefik.http.middlewares.middleware02.buffering.retryexpression=foobar" - "traefik.http.middlewares.middleware03.buffering.memrequestbodybytes=42"
- "traefik.http.middlewares.middleware03.chain.middlewares=foobar, foobar" - "traefik.http.middlewares.middleware03.buffering.memresponsebodybytes=42"
- "traefik.http.middlewares.middleware04.circuitbreaker.expression=foobar" - "traefik.http.middlewares.middleware03.buffering.retryexpression=foobar"
- "traefik.http.middlewares.middleware04.circuitbreaker.checkperiod=42s" - "traefik.http.middlewares.middleware04.chain.middlewares=foobar, foobar"
- "traefik.http.middlewares.middleware04.circuitbreaker.fallbackduration=42s" - "traefik.http.middlewares.middleware05.circuitbreaker.checkperiod=42s"
- "traefik.http.middlewares.middleware04.circuitbreaker.recoveryduration=42s" - "traefik.http.middlewares.middleware05.circuitbreaker.expression=foobar"
- "traefik.http.middlewares.middleware05.compress=true" - "traefik.http.middlewares.middleware05.circuitbreaker.fallbackduration=42s"
- "traefik.http.middlewares.middleware05.compress.excludedcontenttypes=foobar, foobar" - "traefik.http.middlewares.middleware05.circuitbreaker.recoveryduration=42s"
- "traefik.http.middlewares.middleware05.compress.minresponsebodybytes=42" - "traefik.http.middlewares.middleware06.compress=true"
- "traefik.http.middlewares.middleware06.contenttype=true" - "traefik.http.middlewares.middleware06.compress.excludedcontenttypes=foobar, foobar"
- "traefik.http.middlewares.middleware07.digestauth.headerfield=foobar" - "traefik.http.middlewares.middleware06.compress.includedcontenttypes=foobar, foobar"
- "traefik.http.middlewares.middleware07.digestauth.realm=foobar" - "traefik.http.middlewares.middleware06.compress.minresponsebodybytes=42"
- "traefik.http.middlewares.middleware07.digestauth.removeheader=true" - "traefik.http.middlewares.middleware07.contenttype=true"
- "traefik.http.middlewares.middleware07.digestauth.users=foobar, foobar" - "traefik.http.middlewares.middleware08.digestauth.headerfield=foobar"
- "traefik.http.middlewares.middleware07.digestauth.usersfile=foobar" - "traefik.http.middlewares.middleware08.digestauth.realm=foobar"
- "traefik.http.middlewares.middleware08.errors.query=foobar" - "traefik.http.middlewares.middleware08.digestauth.removeheader=true"
- "traefik.http.middlewares.middleware08.errors.service=foobar" - "traefik.http.middlewares.middleware08.digestauth.users=foobar, foobar"
- "traefik.http.middlewares.middleware08.errors.status=foobar, foobar" - "traefik.http.middlewares.middleware08.digestauth.usersfile=foobar"
- "traefik.http.middlewares.middleware09.forwardauth.address=foobar" - "traefik.http.middlewares.middleware09.errors.query=foobar"
- "traefik.http.middlewares.middleware09.forwardauth.authresponseheaders=foobar, foobar" - "traefik.http.middlewares.middleware09.errors.service=foobar"
- "traefik.http.middlewares.middleware09.forwardauth.authresponseheadersregex=foobar" - "traefik.http.middlewares.middleware09.errors.status=foobar, foobar"
- "traefik.http.middlewares.middleware09.forwardauth.authrequestheaders=foobar, foobar" - "traefik.http.middlewares.middleware10.forwardauth.addauthcookiestoresponse=foobar, foobar"
- "traefik.http.middlewares.middleware09.forwardauth.tls.ca=foobar" - "traefik.http.middlewares.middleware10.forwardauth.address=foobar"
- "traefik.http.middlewares.middleware09.forwardauth.tls.cert=foobar" - "traefik.http.middlewares.middleware10.forwardauth.authrequestheaders=foobar, foobar"
- "traefik.http.middlewares.middleware09.forwardauth.tls.insecureskipverify=true" - "traefik.http.middlewares.middleware10.forwardauth.authresponseheaders=foobar, foobar"
- "traefik.http.middlewares.middleware09.forwardauth.tls.key=foobar" - "traefik.http.middlewares.middleware10.forwardauth.authresponseheadersregex=foobar"
- "traefik.http.middlewares.middleware09.forwardauth.trustforwardheader=true" - "traefik.http.middlewares.middleware10.forwardauth.tls.ca=foobar"
- "traefik.http.middlewares.middleware10.headers.accesscontrolallowcredentials=true" - "traefik.http.middlewares.middleware10.forwardauth.tls.cert=foobar"
- "traefik.http.middlewares.middleware10.headers.accesscontrolallowheaders=foobar, foobar" - "traefik.http.middlewares.middleware10.forwardauth.tls.insecureskipverify=true"
- "traefik.http.middlewares.middleware10.headers.accesscontrolallowmethods=foobar, foobar" - "traefik.http.middlewares.middleware10.forwardauth.tls.key=foobar"
- "traefik.http.middlewares.middleware10.headers.accesscontrolalloworiginlist=foobar, foobar" - "traefik.http.middlewares.middleware10.forwardauth.trustforwardheader=true"
- "traefik.http.middlewares.middleware10.headers.accesscontrolalloworiginlistregex=foobar, foobar" - "traefik.http.middlewares.middleware11.grpcweb.alloworigins=foobar, foobar"
- "traefik.http.middlewares.middleware10.headers.accesscontrolexposeheaders=foobar, foobar" - "traefik.http.middlewares.middleware12.headers.accesscontrolallowcredentials=true"
- "traefik.http.middlewares.middleware10.headers.accesscontrolmaxage=42" - "traefik.http.middlewares.middleware12.headers.accesscontrolallowheaders=foobar, foobar"
- "traefik.http.middlewares.middleware10.headers.addvaryheader=true" - "traefik.http.middlewares.middleware12.headers.accesscontrolallowmethods=foobar, foobar"
- "traefik.http.middlewares.middleware10.headers.allowedhosts=foobar, foobar" - "traefik.http.middlewares.middleware12.headers.accesscontrolalloworiginlist=foobar, foobar"
- "traefik.http.middlewares.middleware10.headers.browserxssfilter=true" - "traefik.http.middlewares.middleware12.headers.accesscontrolalloworiginlistregex=foobar, foobar"
- "traefik.http.middlewares.middleware10.headers.contentsecuritypolicy=foobar" - "traefik.http.middlewares.middleware12.headers.accesscontrolexposeheaders=foobar, foobar"
- "traefik.http.middlewares.middleware10.headers.contenttypenosniff=true" - "traefik.http.middlewares.middleware12.headers.accesscontrolmaxage=42"
- "traefik.http.middlewares.middleware10.headers.custombrowserxssvalue=foobar" - "traefik.http.middlewares.middleware12.headers.addvaryheader=true"
- "traefik.http.middlewares.middleware10.headers.customframeoptionsvalue=foobar" - "traefik.http.middlewares.middleware12.headers.allowedhosts=foobar, foobar"
- "traefik.http.middlewares.middleware10.headers.customrequestheaders.name0=foobar" - "traefik.http.middlewares.middleware12.headers.browserxssfilter=true"
- "traefik.http.middlewares.middleware10.headers.customrequestheaders.name1=foobar" - "traefik.http.middlewares.middleware12.headers.contentsecuritypolicy=foobar"
- "traefik.http.middlewares.middleware10.headers.customresponseheaders.name0=foobar" - "traefik.http.middlewares.middleware12.headers.contenttypenosniff=true"
- "traefik.http.middlewares.middleware10.headers.customresponseheaders.name1=foobar" - "traefik.http.middlewares.middleware12.headers.custombrowserxssvalue=foobar"
- "traefik.http.middlewares.middleware10.headers.forcestsheader=true" - "traefik.http.middlewares.middleware12.headers.customframeoptionsvalue=foobar"
- "traefik.http.middlewares.middleware10.headers.framedeny=true" - "traefik.http.middlewares.middleware12.headers.customrequestheaders.name0=foobar"
- "traefik.http.middlewares.middleware10.headers.hostsproxyheaders=foobar, foobar" - "traefik.http.middlewares.middleware12.headers.customrequestheaders.name1=foobar"
- "traefik.http.middlewares.middleware10.headers.isdevelopment=true" - "traefik.http.middlewares.middleware12.headers.customresponseheaders.name0=foobar"
- "traefik.http.middlewares.middleware10.headers.permissionspolicy=foobar" - "traefik.http.middlewares.middleware12.headers.customresponseheaders.name1=foobar"
- "traefik.http.middlewares.middleware10.headers.publickey=foobar" - "traefik.http.middlewares.middleware12.headers.forcestsheader=true"
- "traefik.http.middlewares.middleware10.headers.referrerpolicy=foobar" - "traefik.http.middlewares.middleware12.headers.framedeny=true"
- "traefik.http.middlewares.middleware10.headers.sslproxyheaders.name0=foobar" - "traefik.http.middlewares.middleware12.headers.hostsproxyheaders=foobar, foobar"
- "traefik.http.middlewares.middleware10.headers.sslproxyheaders.name1=foobar" - "traefik.http.middlewares.middleware12.headers.isdevelopment=true"
- "traefik.http.middlewares.middleware10.headers.stsincludesubdomains=true" - "traefik.http.middlewares.middleware12.headers.permissionspolicy=foobar"
- "traefik.http.middlewares.middleware10.headers.stspreload=true" - "traefik.http.middlewares.middleware12.headers.publickey=foobar"
- "traefik.http.middlewares.middleware10.headers.stsseconds=42" - "traefik.http.middlewares.middleware12.headers.referrerpolicy=foobar"
- "traefik.http.middlewares.middleware11.ipwhitelist.ipstrategy.depth=42" - "traefik.http.middlewares.middleware12.headers.sslproxyheaders.name0=foobar"
- "traefik.http.middlewares.middleware11.ipwhitelist.ipstrategy.excludedips=foobar, foobar" - "traefik.http.middlewares.middleware12.headers.sslproxyheaders.name1=foobar"
- "traefik.http.middlewares.middleware12.ipwhitelist.sourcerange=foobar, foobar" - "traefik.http.middlewares.middleware12.headers.stsincludesubdomains=true"
- "traefik.http.middlewares.middleware12.ipallowlist.ipstrategy.depth=42" - "traefik.http.middlewares.middleware12.headers.stspreload=true"
- "traefik.http.middlewares.middleware12.ipallowlist.ipstrategy.excludedips=foobar, foobar" - "traefik.http.middlewares.middleware12.headers.stsseconds=42"
- "traefik.http.middlewares.middleware12.ipallowlist.sourcerange=foobar, foobar" - "traefik.http.middlewares.middleware13.ipallowlist.ipstrategy=true"
- "traefik.http.middlewares.middleware12.ipallowlist.rejectstatuscode=404" - "traefik.http.middlewares.middleware13.ipallowlist.ipstrategy.depth=42"
- "traefik.http.middlewares.middleware13.inflightreq.amount=42" - "traefik.http.middlewares.middleware13.ipallowlist.ipstrategy.excludedips=foobar, foobar"
- "traefik.http.middlewares.middleware13.inflightreq.sourcecriterion.ipstrategy.depth=42" - "traefik.http.middlewares.middleware13.ipallowlist.rejectstatuscode=42"
- "traefik.http.middlewares.middleware13.inflightreq.sourcecriterion.ipstrategy.excludedips=foobar, foobar" - "traefik.http.middlewares.middleware13.ipallowlist.sourcerange=foobar, foobar"
- "traefik.http.middlewares.middleware13.inflightreq.sourcecriterion.requestheadername=foobar" - "traefik.http.middlewares.middleware14.ipwhitelist.ipstrategy=true"
- "traefik.http.middlewares.middleware13.inflightreq.sourcecriterion.requesthost=true" - "traefik.http.middlewares.middleware14.ipwhitelist.ipstrategy.depth=42"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.issuer.commonname=true" - "traefik.http.middlewares.middleware14.ipwhitelist.ipstrategy.excludedips=foobar, foobar"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.issuer.country=true" - "traefik.http.middlewares.middleware14.ipwhitelist.sourcerange=foobar, foobar"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.issuer.domaincomponent=true" - "traefik.http.middlewares.middleware15.inflightreq.amount=42"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.issuer.locality=true" - "traefik.http.middlewares.middleware15.inflightreq.sourcecriterion.ipstrategy.depth=42"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.issuer.organization=true" - "traefik.http.middlewares.middleware15.inflightreq.sourcecriterion.ipstrategy.excludedips=foobar, foobar"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.issuer.province=true" - "traefik.http.middlewares.middleware15.inflightreq.sourcecriterion.requestheadername=foobar"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.issuer.serialnumber=true" - "traefik.http.middlewares.middleware15.inflightreq.sourcecriterion.requesthost=true"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.notafter=true" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.issuer.commonname=true"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.notbefore=true" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.issuer.country=true"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.sans=true" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.issuer.domaincomponent=true"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.serialnumber=true" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.issuer.locality=true"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.subject.commonname=true" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.issuer.organization=true"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.subject.country=true" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.issuer.province=true"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.subject.domaincomponent=true" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.issuer.serialnumber=true"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.subject.locality=true" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.notafter=true"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.subject.organization=true" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.notbefore=true"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.subject.organizationalunit=true" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.sans=true"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.subject.province=true" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.serialnumber=true"
- "traefik.http.middlewares.middleware14.passtlsclientcert.info.subject.serialnumber=true" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.subject.commonname=true"
- "traefik.http.middlewares.middleware14.passtlsclientcert.pem=true" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.subject.country=true"
- "traefik.http.middlewares.middleware15.plugin.foobar.foo=bar" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.subject.domaincomponent=true"
- "traefik.http.middlewares.middleware16.ratelimit.average=42" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.subject.locality=true"
- "traefik.http.middlewares.middleware16.ratelimit.burst=42" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.subject.organization=true"
- "traefik.http.middlewares.middleware16.ratelimit.period=42" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.subject.organizationalunit=true"
- "traefik.http.middlewares.middleware16.ratelimit.sourcecriterion.ipstrategy.depth=42" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.subject.province=true"
- "traefik.http.middlewares.middleware16.ratelimit.sourcecriterion.ipstrategy.excludedips=foobar, foobar" - "traefik.http.middlewares.middleware16.passtlsclientcert.info.subject.serialnumber=true"
- "traefik.http.middlewares.middleware16.ratelimit.sourcecriterion.requestheadername=foobar" - "traefik.http.middlewares.middleware16.passtlsclientcert.pem=true"
- "traefik.http.middlewares.middleware16.ratelimit.sourcecriterion.requesthost=true" - "traefik.http.middlewares.middleware17.plugin.pluginconf0.name0=foobar"
- "traefik.http.middlewares.middleware17.redirectregex.permanent=true" - "traefik.http.middlewares.middleware17.plugin.pluginconf0.name1=foobar"
- "traefik.http.middlewares.middleware17.redirectregex.regex=foobar" - "traefik.http.middlewares.middleware17.plugin.pluginconf1.name0=foobar"
- "traefik.http.middlewares.middleware17.redirectregex.replacement=foobar" - "traefik.http.middlewares.middleware17.plugin.pluginconf1.name1=foobar"
- "traefik.http.middlewares.middleware18.redirectscheme.permanent=true" - "traefik.http.middlewares.middleware18.ratelimit.average=42"
- "traefik.http.middlewares.middleware18.redirectscheme.port=foobar" - "traefik.http.middlewares.middleware18.ratelimit.burst=42"
- "traefik.http.middlewares.middleware18.redirectscheme.scheme=foobar" - "traefik.http.middlewares.middleware18.ratelimit.period=42s"
- "traefik.http.middlewares.middleware19.replacepath.path=foobar" - "traefik.http.middlewares.middleware18.ratelimit.sourcecriterion.ipstrategy.depth=42"
- "traefik.http.middlewares.middleware20.replacepathregex.regex=foobar" - "traefik.http.middlewares.middleware18.ratelimit.sourcecriterion.ipstrategy.excludedips=foobar, foobar"
- "traefik.http.middlewares.middleware20.replacepathregex.replacement=foobar" - "traefik.http.middlewares.middleware18.ratelimit.sourcecriterion.requestheadername=foobar"
- "traefik.http.middlewares.middleware21.retry.attempts=42" - "traefik.http.middlewares.middleware18.ratelimit.sourcecriterion.requesthost=true"
- "traefik.http.middlewares.middleware21.retry.initialinterval=42" - "traefik.http.middlewares.middleware19.redirectregex.permanent=true"
- "traefik.http.middlewares.middleware22.stripprefix.prefixes=foobar, foobar" - "traefik.http.middlewares.middleware19.redirectregex.regex=foobar"
- "traefik.http.middlewares.middleware23.stripprefixregex.regex=foobar, foobar" - "traefik.http.middlewares.middleware19.redirectregex.replacement=foobar"
- "traefik.http.middlewares.middleware24.grpcweb.alloworigins=foobar, foobar" - "traefik.http.middlewares.middleware20.redirectscheme.permanent=true"
- "traefik.http.middlewares.middleware20.redirectscheme.port=foobar"
- "traefik.http.middlewares.middleware20.redirectscheme.scheme=foobar"
- "traefik.http.middlewares.middleware21.replacepath.path=foobar"
- "traefik.http.middlewares.middleware22.replacepathregex.regex=foobar"
- "traefik.http.middlewares.middleware22.replacepathregex.replacement=foobar"
- "traefik.http.middlewares.middleware23.retry.attempts=42"
- "traefik.http.middlewares.middleware23.retry.initialinterval=42s"
- "traefik.http.middlewares.middleware24.stripprefix.prefixes=foobar, foobar"
- "traefik.http.middlewares.middleware25.stripprefixregex.regex=foobar, foobar"
- "traefik.http.routers.router0.entrypoints=foobar, foobar" - "traefik.http.routers.router0.entrypoints=foobar, foobar"
- "traefik.http.routers.router0.middlewares=foobar, foobar" - "traefik.http.routers.router0.middlewares=foobar, foobar"
- "traefik.http.routers.router0.priority=42" - "traefik.http.routers.router0.priority=42"
@ -143,35 +152,37 @@
- "traefik.http.routers.router1.tls.domains[1].main=foobar" - "traefik.http.routers.router1.tls.domains[1].main=foobar"
- "traefik.http.routers.router1.tls.domains[1].sans=foobar, foobar" - "traefik.http.routers.router1.tls.domains[1].sans=foobar, foobar"
- "traefik.http.routers.router1.tls.options=foobar" - "traefik.http.routers.router1.tls.options=foobar"
- "traefik.http.services.service01.loadbalancer.healthcheck.followredirects=true" - "traefik.http.services.service02.loadbalancer.healthcheck.followredirects=true"
- "traefik.http.services.service01.loadbalancer.healthcheck.headers.name0=foobar" - "traefik.http.services.service02.loadbalancer.healthcheck.headers.name0=foobar"
- "traefik.http.services.service01.loadbalancer.healthcheck.headers.name1=foobar" - "traefik.http.services.service02.loadbalancer.healthcheck.headers.name1=foobar"
- "traefik.http.services.service01.loadbalancer.healthcheck.hostname=foobar" - "traefik.http.services.service02.loadbalancer.healthcheck.hostname=foobar"
- "traefik.http.services.service01.loadbalancer.healthcheck.interval=foobar" - "traefik.http.services.service02.loadbalancer.healthcheck.interval=42s"
- "traefik.http.services.service01.loadbalancer.healthcheck.path=foobar" - "traefik.http.services.service02.loadbalancer.healthcheck.method=foobar"
- "traefik.http.services.service01.loadbalancer.healthcheck.method=foobar" - "traefik.http.services.service02.loadbalancer.healthcheck.mode=foobar"
- "traefik.http.services.service01.loadbalancer.healthcheck.status=42" - "traefik.http.services.service02.loadbalancer.healthcheck.path=foobar"
- "traefik.http.services.service01.loadbalancer.healthcheck.port=42" - "traefik.http.services.service02.loadbalancer.healthcheck.port=42"
- "traefik.http.services.service01.loadbalancer.healthcheck.scheme=foobar" - "traefik.http.services.service02.loadbalancer.healthcheck.scheme=foobar"
- "traefik.http.services.service01.loadbalancer.healthcheck.mode=foobar" - "traefik.http.services.service02.loadbalancer.healthcheck.status=42"
- "traefik.http.services.service01.loadbalancer.healthcheck.timeout=foobar" - "traefik.http.services.service02.loadbalancer.healthcheck.timeout=42s"
- "traefik.http.services.service01.loadbalancer.passhostheader=true" - "traefik.http.services.service02.loadbalancer.passhostheader=true"
- "traefik.http.services.service01.loadbalancer.responseforwarding.flushinterval=foobar" - "traefik.http.services.service02.loadbalancer.responseforwarding.flushinterval=42s"
- "traefik.http.services.service01.loadbalancer.serverstransport=foobar" - "traefik.http.services.service02.loadbalancer.serverstransport=foobar"
- "traefik.http.services.service01.loadbalancer.sticky.cookie=true" - "traefik.http.services.service02.loadbalancer.sticky=true"
- "traefik.http.services.service01.loadbalancer.sticky.cookie.httponly=true" - "traefik.http.services.service02.loadbalancer.sticky.cookie=true"
- "traefik.http.services.service01.loadbalancer.sticky.cookie.name=foobar" - "traefik.http.services.service02.loadbalancer.sticky.cookie.httponly=true"
- "traefik.http.services.service01.loadbalancer.sticky.cookie.samesite=foobar" - "traefik.http.services.service02.loadbalancer.sticky.cookie.maxage=42"
- "traefik.http.services.service01.loadbalancer.sticky.cookie.secure=true" - "traefik.http.services.service02.loadbalancer.sticky.cookie.name=foobar"
- "traefik.http.services.service01.loadbalancer.server.port=foobar" - "traefik.http.services.service02.loadbalancer.sticky.cookie.samesite=foobar"
- "traefik.http.services.service01.loadbalancer.server.scheme=foobar" - "traefik.http.services.service02.loadbalancer.sticky.cookie.secure=true"
- "traefik.tcp.middlewares.tcpmiddleware00.inflightconn.amount=42" - "traefik.http.services.service02.loadbalancer.server.port=foobar"
- "traefik.tcp.middlewares.tcpmiddleware01.ipwhitelist.sourcerange=foobar, foobar" - "traefik.http.services.service02.loadbalancer.server.scheme=foobar"
- "traefik.tcp.middlewares.tcpmiddleware02.ipallowlist.sourcerange=foobar, foobar" - "traefik.tcp.middlewares.tcpmiddleware01.ipallowlist.sourcerange=foobar, foobar"
- "traefik.tcp.middlewares.tcpmiddleware02.ipwhitelist.sourcerange=foobar, foobar"
- "traefik.tcp.middlewares.tcpmiddleware03.inflightconn.amount=42"
- "traefik.tcp.routers.tcprouter0.entrypoints=foobar, foobar" - "traefik.tcp.routers.tcprouter0.entrypoints=foobar, foobar"
- "traefik.tcp.routers.tcprouter0.middlewares=foobar, foobar" - "traefik.tcp.routers.tcprouter0.middlewares=foobar, foobar"
- "traefik.tcp.routers.tcprouter0.rule=foobar"
- "traefik.tcp.routers.tcprouter0.priority=42" - "traefik.tcp.routers.tcprouter0.priority=42"
- "traefik.tcp.routers.tcprouter0.rule=foobar"
- "traefik.tcp.routers.tcprouter0.service=foobar" - "traefik.tcp.routers.tcprouter0.service=foobar"
- "traefik.tcp.routers.tcprouter0.tls=true" - "traefik.tcp.routers.tcprouter0.tls=true"
- "traefik.tcp.routers.tcprouter0.tls.certresolver=foobar" - "traefik.tcp.routers.tcprouter0.tls.certresolver=foobar"
@ -183,8 +194,8 @@
- "traefik.tcp.routers.tcprouter0.tls.passthrough=true" - "traefik.tcp.routers.tcprouter0.tls.passthrough=true"
- "traefik.tcp.routers.tcprouter1.entrypoints=foobar, foobar" - "traefik.tcp.routers.tcprouter1.entrypoints=foobar, foobar"
- "traefik.tcp.routers.tcprouter1.middlewares=foobar, foobar" - "traefik.tcp.routers.tcprouter1.middlewares=foobar, foobar"
- "traefik.tcp.routers.tcprouter1.rule=foobar"
- "traefik.tcp.routers.tcprouter1.priority=42" - "traefik.tcp.routers.tcprouter1.priority=42"
- "traefik.tcp.routers.tcprouter1.rule=foobar"
- "traefik.tcp.routers.tcprouter1.service=foobar" - "traefik.tcp.routers.tcprouter1.service=foobar"
- "traefik.tcp.routers.tcprouter1.tls=true" - "traefik.tcp.routers.tcprouter1.tls=true"
- "traefik.tcp.routers.tcprouter1.tls.certresolver=foobar" - "traefik.tcp.routers.tcprouter1.tls.certresolver=foobar"
@ -194,22 +205,13 @@
- "traefik.tcp.routers.tcprouter1.tls.domains[1].sans=foobar, foobar" - "traefik.tcp.routers.tcprouter1.tls.domains[1].sans=foobar, foobar"
- "traefik.tcp.routers.tcprouter1.tls.options=foobar" - "traefik.tcp.routers.tcprouter1.tls.options=foobar"
- "traefik.tcp.routers.tcprouter1.tls.passthrough=true" - "traefik.tcp.routers.tcprouter1.tls.passthrough=true"
- "traefik.tcp.services.tcpservice01.loadbalancer.proxyprotocol=true"
- "traefik.tcp.services.tcpservice01.loadbalancer.proxyprotocol.version=42" - "traefik.tcp.services.tcpservice01.loadbalancer.proxyprotocol.version=42"
- "traefik.tcp.services.tcpservice01.loadbalancer.serverstransport=foobar"
- "traefik.tcp.services.tcpservice01.loadbalancer.server.port=foobar" - "traefik.tcp.services.tcpservice01.loadbalancer.server.port=foobar"
- "traefik.tcp.services.tcpservice01.loadbalancer.server.tls=true" - "traefik.tcp.services.tcpservice01.loadbalancer.server.tls=true"
- "traefik.tcp.services.tcpservice01.loadbalancer.serverstransport=foobar"
- "traefik.udp.routers.udprouter0.entrypoints=foobar, foobar" - "traefik.udp.routers.udprouter0.entrypoints=foobar, foobar"
- "traefik.udp.routers.udprouter0.service=foobar" - "traefik.udp.routers.udprouter0.service=foobar"
- "traefik.udp.routers.udprouter1.entrypoints=foobar, foobar" - "traefik.udp.routers.udprouter1.entrypoints=foobar, foobar"
- "traefik.udp.routers.udprouter1.service=foobar" - "traefik.udp.routers.udprouter1.service=foobar"
- "traefik.udp.services.udpservice01.loadbalancer.server.port=foobar" - "traefik.udp.services.udpservice01.loadbalancer.server.port=foobar"
- "traefik.tls.stores.Store0.defaultcertificate.certfile=foobar"
- "traefik.tls.stores.Store0.defaultcertificate.keyfile=foobar"
- "traefik.tls.stores.Store0.defaultgeneratedcert.domain.main=foobar"
- "traefik.tls.stores.Store0.defaultgeneratedcert.domain.sans=foobar, foobar"
- "traefik.tls.stores.Store0.defaultgeneratedcert.resolver=foobar"
- "traefik.tls.stores.Store1.defaultcertificate.certfile=foobar"
- "traefik.tls.stores.Store1.defaultcertificate.keyfile=foobar"
- "traefik.tls.stores.Store1.defaultgeneratedcert.domain.main=foobar"
- "traefik.tls.stores.Store1.defaultgeneratedcert.domain.sans=foobar, foobar"
- "traefik.tls.stores.Store1.defaultgeneratedcert.resolver=foobar"

View file

@ -1,3 +1,5 @@
## CODE GENERATED AUTOMATICALLY
## THIS FILE MUST NOT BE EDITED BY HAND
[http] [http]
[http.routers] [http.routers]
[http.routers.Router0] [http.routers.Router0]
@ -36,22 +38,28 @@
sans = ["foobar", "foobar"] sans = ["foobar", "foobar"]
[http.services] [http.services]
[http.services.Service01] [http.services.Service01]
[http.services.Service01.loadBalancer] [http.services.Service01.failover]
service = "foobar"
fallback = "foobar"
[http.services.Service01.failover.healthCheck]
[http.services.Service02]
[http.services.Service02.loadBalancer]
passHostHeader = true passHostHeader = true
serversTransport = "foobar" serversTransport = "foobar"
[http.services.Service01.loadBalancer.sticky] [http.services.Service02.loadBalancer.sticky]
[http.services.Service01.loadBalancer.sticky.cookie] [http.services.Service02.loadBalancer.sticky.cookie]
name = "foobar" name = "foobar"
secure = true secure = true
httpOnly = true httpOnly = true
sameSite = "foobar" sameSite = "foobar"
maxAge = 42
[[http.services.Service01.loadBalancer.servers]] [[http.services.Service02.loadBalancer.servers]]
url = "foobar" url = "foobar"
[[http.services.Service01.loadBalancer.servers]] [[http.services.Service02.loadBalancer.servers]]
url = "foobar" url = "foobar"
[http.services.Service01.loadBalancer.healthCheck] [http.services.Service02.loadBalancer.healthCheck]
scheme = "foobar" scheme = "foobar"
mode = "foobar" mode = "foobar"
path = "foobar" path = "foobar"
@ -62,107 +70,106 @@
timeout = "42s" timeout = "42s"
hostname = "foobar" hostname = "foobar"
followRedirects = true followRedirects = true
[http.services.Service01.loadBalancer.healthCheck.headers] [http.services.Service02.loadBalancer.healthCheck.headers]
name0 = "foobar" name0 = "foobar"
name1 = "foobar" name1 = "foobar"
[http.services.Service01.loadBalancer.responseForwarding] [http.services.Service02.loadBalancer.responseForwarding]
flushInterval = "42s" flushInterval = "42s"
[http.services.Service02] [http.services.Service03]
[http.services.Service02.mirroring] [http.services.Service03.mirroring]
service = "foobar" service = "foobar"
maxBodySize = 42 maxBodySize = 42
[http.services.Service02.mirroring.healthCheck] [[http.services.Service03.mirroring.mirrors]]
[[http.services.Service02.mirroring.mirrors]]
name = "foobar" name = "foobar"
percent = 42 percent = 42
[[http.services.Service02.mirroring.mirrors]] [[http.services.Service03.mirroring.mirrors]]
name = "foobar" name = "foobar"
percent = 42 percent = 42
[http.services.Service03] [http.services.Service03.mirroring.healthCheck]
[http.services.Service03.weighted] [http.services.Service04]
[http.services.Service03.weighted.healthCheck] [http.services.Service04.weighted]
[[http.services.Service03.weighted.services]] [[http.services.Service04.weighted.services]]
name = "foobar" name = "foobar"
weight = 42 weight = 42
[[http.services.Service03.weighted.services]] [[http.services.Service04.weighted.services]]
name = "foobar" name = "foobar"
weight = 42 weight = 42
[http.services.Service03.weighted.sticky] [http.services.Service04.weighted.sticky]
[http.services.Service03.weighted.sticky.cookie] [http.services.Service04.weighted.sticky.cookie]
name = "foobar" name = "foobar"
secure = true secure = true
httpOnly = true httpOnly = true
sameSite = "foobar" sameSite = "foobar"
[http.services.Service04] maxAge = 42
[http.services.Service04.failover] [http.services.Service04.weighted.healthCheck]
service = "foobar"
fallback = "foobar"
[http.services.Service04.failover.healthCheck]
[http.middlewares] [http.middlewares]
[http.middlewares.Middleware00]
[http.middlewares.Middleware00.addPrefix]
prefix = "foobar"
[http.middlewares.Middleware01] [http.middlewares.Middleware01]
[http.middlewares.Middleware01.basicAuth] [http.middlewares.Middleware01.addPrefix]
prefix = "foobar"
[http.middlewares.Middleware02]
[http.middlewares.Middleware02.basicAuth]
users = ["foobar", "foobar"] users = ["foobar", "foobar"]
usersFile = "foobar" usersFile = "foobar"
realm = "foobar" realm = "foobar"
removeHeader = true removeHeader = true
headerField = "foobar" headerField = "foobar"
[http.middlewares.Middleware02] [http.middlewares.Middleware03]
[http.middlewares.Middleware02.buffering] [http.middlewares.Middleware03.buffering]
maxRequestBodyBytes = 42 maxRequestBodyBytes = 42
memRequestBodyBytes = 42 memRequestBodyBytes = 42
maxResponseBodyBytes = 42 maxResponseBodyBytes = 42
memResponseBodyBytes = 42 memResponseBodyBytes = 42
retryExpression = "foobar" retryExpression = "foobar"
[http.middlewares.Middleware03]
[http.middlewares.Middleware03.chain]
middlewares = ["foobar", "foobar"]
[http.middlewares.Middleware04] [http.middlewares.Middleware04]
[http.middlewares.Middleware04.circuitBreaker] [http.middlewares.Middleware04.chain]
middlewares = ["foobar", "foobar"]
[http.middlewares.Middleware05]
[http.middlewares.Middleware05.circuitBreaker]
expression = "foobar" expression = "foobar"
checkPeriod = "42s" checkPeriod = "42s"
fallbackDuration = "42s" fallbackDuration = "42s"
recoveryDuration = "42s" recoveryDuration = "42s"
[http.middlewares.Middleware05]
[http.middlewares.Middleware05.compress]
excludedContentTypes = ["foobar", "foobar"]
minResponseBodyBytes = 42
[http.middlewares.Middleware06] [http.middlewares.Middleware06]
[http.middlewares.Middleware06.contentType] [http.middlewares.Middleware06.compress]
excludedContentTypes = ["foobar", "foobar"]
includedContentTypes = ["foobar", "foobar"]
minResponseBodyBytes = 42
[http.middlewares.Middleware07] [http.middlewares.Middleware07]
[http.middlewares.Middleware07.digestAuth] [http.middlewares.Middleware07.contentType]
[http.middlewares.Middleware08]
[http.middlewares.Middleware08.digestAuth]
users = ["foobar", "foobar"] users = ["foobar", "foobar"]
usersFile = "foobar" usersFile = "foobar"
removeHeader = true removeHeader = true
realm = "foobar" realm = "foobar"
headerField = "foobar" headerField = "foobar"
[http.middlewares.Middleware08] [http.middlewares.Middleware09]
[http.middlewares.Middleware08.errors] [http.middlewares.Middleware09.errors]
status = ["foobar", "foobar"] status = ["foobar", "foobar"]
service = "foobar" service = "foobar"
query = "foobar" query = "foobar"
[http.middlewares.Middleware09] [http.middlewares.Middleware10]
[http.middlewares.Middleware09.forwardAuth] [http.middlewares.Middleware10.forwardAuth]
address = "foobar" address = "foobar"
trustForwardHeader = true trustForwardHeader = true
authResponseHeaders = ["foobar", "foobar"] authResponseHeaders = ["foobar", "foobar"]
authResponseHeadersRegex = "foobar" authResponseHeadersRegex = "foobar"
authRequestHeaders = ["foobar", "foobar"] authRequestHeaders = ["foobar", "foobar"]
[http.middlewares.Middleware09.forwardAuth.tls] addAuthCookiesToResponse = ["foobar", "foobar"]
[http.middlewares.Middleware10.forwardAuth.tls]
ca = "foobar" ca = "foobar"
cert = "foobar" cert = "foobar"
key = "foobar" key = "foobar"
insecureSkipVerify = true insecureSkipVerify = true
[http.middlewares.Middleware10] [http.middlewares.Middleware11]
[http.middlewares.Middleware10.headers] [http.middlewares.Middleware11.grpcWeb]
allowOrigins = ["foobar", "foobar"]
[http.middlewares.Middleware12]
[http.middlewares.Middleware12.headers]
accessControlAllowCredentials = true accessControlAllowCredentials = true
accessControlAllowHeaders = ["foobar", "foobar"] accessControlAllowHeaders = ["foobar", "foobar"]
accessControlAllowMethods = ["foobar", "foobar"] accessControlAllowMethods = ["foobar", "foobar"]
@ -187,46 +194,46 @@
referrerPolicy = "foobar" referrerPolicy = "foobar"
permissionsPolicy = "foobar" permissionsPolicy = "foobar"
isDevelopment = true isDevelopment = true
[http.middlewares.Middleware10.headers.customRequestHeaders] [http.middlewares.Middleware12.headers.customRequestHeaders]
name0 = "foobar" name0 = "foobar"
name1 = "foobar" name1 = "foobar"
[http.middlewares.Middleware10.headers.customResponseHeaders] [http.middlewares.Middleware12.headers.customResponseHeaders]
name0 = "foobar" name0 = "foobar"
name1 = "foobar" name1 = "foobar"
[http.middlewares.Middleware10.headers.sslProxyHeaders] [http.middlewares.Middleware12.headers.sslProxyHeaders]
name0 = "foobar" name0 = "foobar"
name1 = "foobar" name1 = "foobar"
[http.middlewares.Middleware11]
[http.middlewares.Middleware11.ipWhiteList]
sourceRange = ["foobar", "foobar"]
[http.middlewares.Middleware11.ipWhiteList.ipStrategy]
depth = 42
excludedIPs = ["foobar", "foobar"]
[http.middlewares.Middleware12]
[http.middlewares.Middleware12.ipAllowList]
sourceRange = ["foobar", "foobar"]
rejectStatusCode = 404
[http.middlewares.Middleware12.ipAllowList.ipStrategy]
depth = 42
excludedIPs = ["foobar", "foobar"]
[http.middlewares.Middleware13] [http.middlewares.Middleware13]
[http.middlewares.Middleware13.inFlightReq] [http.middlewares.Middleware13.ipAllowList]
amount = 42 sourceRange = ["foobar", "foobar"]
[http.middlewares.Middleware13.inFlightReq.sourceCriterion] rejectStatusCode = 42
requestHeaderName = "foobar" [http.middlewares.Middleware13.ipAllowList.ipStrategy]
requestHost = true
[http.middlewares.Middleware13.inFlightReq.sourceCriterion.ipStrategy]
depth = 42 depth = 42
excludedIPs = ["foobar", "foobar"] excludedIPs = ["foobar", "foobar"]
[http.middlewares.Middleware14] [http.middlewares.Middleware14]
[http.middlewares.Middleware14.passTLSClientCert] [http.middlewares.Middleware14.ipWhiteList]
sourceRange = ["foobar", "foobar"]
[http.middlewares.Middleware14.ipWhiteList.ipStrategy]
depth = 42
excludedIPs = ["foobar", "foobar"]
[http.middlewares.Middleware15]
[http.middlewares.Middleware15.inFlightReq]
amount = 42
[http.middlewares.Middleware15.inFlightReq.sourceCriterion]
requestHeaderName = "foobar"
requestHost = true
[http.middlewares.Middleware15.inFlightReq.sourceCriterion.ipStrategy]
depth = 42
excludedIPs = ["foobar", "foobar"]
[http.middlewares.Middleware16]
[http.middlewares.Middleware16.passTLSClientCert]
pem = true pem = true
[http.middlewares.Middleware14.passTLSClientCert.info] [http.middlewares.Middleware16.passTLSClientCert.info]
notAfter = true notAfter = true
notBefore = true notBefore = true
sans = true sans = true
serialNumber = true serialNumber = true
[http.middlewares.Middleware14.passTLSClientCert.info.subject] [http.middlewares.Middleware16.passTLSClientCert.info.subject]
country = true country = true
province = true province = true
locality = true locality = true
@ -235,7 +242,7 @@
commonName = true commonName = true
serialNumber = true serialNumber = true
domainComponent = true domainComponent = true
[http.middlewares.Middleware14.passTLSClientCert.info.issuer] [http.middlewares.Middleware16.passTLSClientCert.info.issuer]
country = true country = true
province = true province = true
locality = true locality = true
@ -243,51 +250,52 @@
commonName = true commonName = true
serialNumber = true serialNumber = true
domainComponent = true domainComponent = true
[http.middlewares.Middleware15] [http.middlewares.Middleware17]
[http.middlewares.Middleware15.plugin] [http.middlewares.Middleware17.plugin]
[http.middlewares.Middleware15.plugin.PluginConf] [http.middlewares.Middleware17.plugin.PluginConf0]
foo = "bar" name0 = "foobar"
[http.middlewares.Middleware16] name1 = "foobar"
[http.middlewares.Middleware16.rateLimit] [http.middlewares.Middleware17.plugin.PluginConf1]
name0 = "foobar"
name1 = "foobar"
[http.middlewares.Middleware18]
[http.middlewares.Middleware18.rateLimit]
average = 42 average = 42
period = "42s" period = "42s"
burst = 42 burst = 42
[http.middlewares.Middleware16.rateLimit.sourceCriterion] [http.middlewares.Middleware18.rateLimit.sourceCriterion]
requestHeaderName = "foobar" requestHeaderName = "foobar"
requestHost = true requestHost = true
[http.middlewares.Middleware16.rateLimit.sourceCriterion.ipStrategy] [http.middlewares.Middleware18.rateLimit.sourceCriterion.ipStrategy]
depth = 42 depth = 42
excludedIPs = ["foobar", "foobar"] excludedIPs = ["foobar", "foobar"]
[http.middlewares.Middleware17] [http.middlewares.Middleware19]
[http.middlewares.Middleware17.redirectRegex] [http.middlewares.Middleware19.redirectRegex]
regex = "foobar" regex = "foobar"
replacement = "foobar" replacement = "foobar"
permanent = true permanent = true
[http.middlewares.Middleware18] [http.middlewares.Middleware20]
[http.middlewares.Middleware18.redirectScheme] [http.middlewares.Middleware20.redirectScheme]
scheme = "foobar" scheme = "foobar"
port = "foobar" port = "foobar"
permanent = true permanent = true
[http.middlewares.Middleware19] [http.middlewares.Middleware21]
[http.middlewares.Middleware19.replacePath] [http.middlewares.Middleware21.replacePath]
path = "foobar" path = "foobar"
[http.middlewares.Middleware20] [http.middlewares.Middleware22]
[http.middlewares.Middleware20.replacePathRegex] [http.middlewares.Middleware22.replacePathRegex]
regex = "foobar" regex = "foobar"
replacement = "foobar" replacement = "foobar"
[http.middlewares.Middleware21] [http.middlewares.Middleware23]
[http.middlewares.Middleware21.retry] [http.middlewares.Middleware23.retry]
attempts = 42 attempts = 42
initialInterval = "42s" initialInterval = "42s"
[http.middlewares.Middleware22]
[http.middlewares.Middleware22.stripPrefix]
prefixes = ["foobar", "foobar"]
[http.middlewares.Middleware23]
[http.middlewares.Middleware23.stripPrefixRegex]
regex = ["foobar", "foobar"]
[http.middlewares.Middleware24] [http.middlewares.Middleware24]
[http.middlewares.Middleware24.grpcWeb] [http.middlewares.Middleware24.stripPrefix]
allowOrigins = ["foobar", "foobar"] prefixes = ["foobar", "foobar"]
[http.middlewares.Middleware25]
[http.middlewares.Middleware25.stripPrefixRegex]
regex = ["foobar", "foobar"]
[http.serversTransports] [http.serversTransports]
[http.serversTransports.ServersTransport0] [http.serversTransports.ServersTransport0]
serverName = "foobar" serverName = "foobar"
@ -304,18 +312,15 @@
[[http.serversTransports.ServersTransport0.certificates]] [[http.serversTransports.ServersTransport0.certificates]]
certFile = "foobar" certFile = "foobar"
keyFile = "foobar" keyFile = "foobar"
[http.serversTransports.ServersTransport0.forwardingTimeouts] [http.serversTransports.ServersTransport0.forwardingTimeouts]
dialTimeout = "42s" dialTimeout = "42s"
responseHeaderTimeout = "42s" responseHeaderTimeout = "42s"
idleConnTimeout = "42s" idleConnTimeout = "42s"
readIdleTimeout = "42s" readIdleTimeout = "42s"
pingTimeout = "42s" pingTimeout = "42s"
[http.serversTransports.ServersTransport0.spiffe] [http.serversTransports.ServersTransport0.spiffe]
ids = ["foobar", "foobar"] ids = ["foobar", "foobar"]
trustDomain = "foobar" trustDomain = "foobar"
[http.serversTransports.ServersTransport1] [http.serversTransports.ServersTransport1]
serverName = "foobar" serverName = "foobar"
insecureSkipVerify = true insecureSkipVerify = true
@ -331,14 +336,12 @@
[[http.serversTransports.ServersTransport1.certificates]] [[http.serversTransports.ServersTransport1.certificates]]
certFile = "foobar" certFile = "foobar"
keyFile = "foobar" keyFile = "foobar"
[http.serversTransports.ServersTransport1.forwardingTimeouts] [http.serversTransports.ServersTransport1.forwardingTimeouts]
dialTimeout = "42s" dialTimeout = "42s"
responseHeaderTimeout = "42s" responseHeaderTimeout = "42s"
idleConnTimeout = "42s" idleConnTimeout = "42s"
readIdleTimeout = "42s" readIdleTimeout = "42s"
pingTimeout = "42s" pingTimeout = "42s"
[http.serversTransports.ServersTransport1.spiffe] [http.serversTransports.ServersTransport1.spiffe]
ids = ["foobar", "foobar"] ids = ["foobar", "foobar"]
trustDomain = "foobar" trustDomain = "foobar"
@ -405,21 +408,21 @@
[[tcp.services.TCPService02.weighted.services]] [[tcp.services.TCPService02.weighted.services]]
name = "foobar" name = "foobar"
weight = 42 weight = 42
[tcp.middlewares] [tcp.middlewares]
[tcp.middlewares.TCPMiddleware00]
[tcp.middlewares.TCPMiddleware00.ipAllowList]
sourceRange = ["foobar", "foobar"]
[tcp.middlewares.TCPMiddleware01] [tcp.middlewares.TCPMiddleware01]
[tcp.middlewares.TCPMiddleware01.inFlightConn] [tcp.middlewares.TCPMiddleware01.ipAllowList]
sourceRange = ["foobar", "foobar"]
[tcp.middlewares.TCPMiddleware02]
[tcp.middlewares.TCPMiddleware02.ipWhiteList]
sourceRange = ["foobar", "foobar"]
[tcp.middlewares.TCPMiddleware03]
[tcp.middlewares.TCPMiddleware03.inFlightConn]
amount = 42 amount = 42
[tcp.serversTransports] [tcp.serversTransports]
[tcp.serversTransports.TCPServersTransport0] [tcp.serversTransports.TCPServersTransport0]
dialTimeout = "42s"
dialKeepAlive = "42s" dialKeepAlive = "42s"
dialTimeout = "42s"
terminationDelay = "42s" terminationDelay = "42s"
[tcp.serversTransports.TCPServersTransport0.tls] [tcp.serversTransports.TCPServersTransport0.tls]
serverName = "foobar" serverName = "foobar"
insecureSkipVerify = true insecureSkipVerify = true
@ -433,16 +436,13 @@
[[tcp.serversTransports.TCPServersTransport0.tls.certificates]] [[tcp.serversTransports.TCPServersTransport0.tls.certificates]]
certFile = "foobar" certFile = "foobar"
keyFile = "foobar" keyFile = "foobar"
[tcp.serversTransports.TCPServersTransport0.tls.spiffe]
[tcp.serversTransports.TCPServersTransport0.spiffe]
ids = ["foobar", "foobar"] ids = ["foobar", "foobar"]
trustDomain = "foobar" trustDomain = "foobar"
[tcp.serversTransports.TCPServersTransport1] [tcp.serversTransports.TCPServersTransport1]
dialTimeout = "42s"
dialKeepAlive = "42s" dialKeepAlive = "42s"
dialTimeout = "42s"
terminationDelay = "42s" terminationDelay = "42s"
[tcp.serversTransports.TCPServersTransport1.tls] [tcp.serversTransports.TCPServersTransport1.tls]
serverName = "foobar" serverName = "foobar"
insecureSkipVerify = true insecureSkipVerify = true
@ -456,8 +456,7 @@
[[tcp.serversTransports.TCPServersTransport1.tls.certificates]] [[tcp.serversTransports.TCPServersTransport1.tls.certificates]]
certFile = "foobar" certFile = "foobar"
keyFile = "foobar" keyFile = "foobar"
[tcp.serversTransports.TCPServersTransport1.tls.spiffe]
[tcp.serversTransports.TCPServersTransport1.spiffe]
ids = ["foobar", "foobar"] ids = ["foobar", "foobar"]
trustDomain = "foobar" trustDomain = "foobar"

View file

@ -1,3 +1,5 @@
## CODE GENERATED AUTOMATICALLY
## THIS FILE MUST NOT BE EDITED BY HAND
http: http:
routers: routers:
Router0: Router0:
@ -46,6 +48,11 @@ http:
- foobar - foobar
services: services:
Service01: Service01:
failover:
service: foobar
fallback: foobar
healthCheck: {}
Service02:
loadBalancer: loadBalancer:
sticky: sticky:
cookie: cookie:
@ -53,6 +60,7 @@ http:
secure: true secure: true
httpOnly: true httpOnly: true
sameSite: foobar sameSite: foobar
maxAge: 42
servers: servers:
- url: foobar - url: foobar
- url: foobar - url: foobar
@ -74,19 +82,18 @@ http:
responseForwarding: responseForwarding:
flushInterval: 42s flushInterval: 42s
serversTransport: foobar serversTransport: foobar
Service02: Service03:
mirroring: mirroring:
service: foobar service: foobar
maxBodySize: 42 maxBodySize: 42
healthCheck: {}
mirrors: mirrors:
- name: foobar - name: foobar
percent: 42 percent: 42
- name: foobar - name: foobar
percent: 42 percent: 42
Service03:
weighted:
healthCheck: {} healthCheck: {}
Service04:
weighted:
services: services:
- name: foobar - name: foobar
weight: 42 weight: 42
@ -98,16 +105,13 @@ http:
secure: true secure: true
httpOnly: true httpOnly: true
sameSite: foobar sameSite: foobar
Service04: maxAge: 42
failover:
service: foobar
fallback: foobar
healthCheck: {} healthCheck: {}
middlewares: middlewares:
Middleware00: Middleware01:
addPrefix: addPrefix:
prefix: foobar prefix: foobar
Middleware01: Middleware02:
basicAuth: basicAuth:
users: users:
- foobar - foobar
@ -116,33 +120,36 @@ http:
realm: foobar realm: foobar
removeHeader: true removeHeader: true
headerField: foobar headerField: foobar
Middleware02: Middleware03:
buffering: buffering:
maxRequestBodyBytes: 42 maxRequestBodyBytes: 42
memRequestBodyBytes: 42 memRequestBodyBytes: 42
maxResponseBodyBytes: 42 maxResponseBodyBytes: 42
memResponseBodyBytes: 42 memResponseBodyBytes: 42
retryExpression: foobar retryExpression: foobar
Middleware03: Middleware04:
chain: chain:
middlewares: middlewares:
- foobar - foobar
- foobar - foobar
Middleware04: Middleware05:
circuitBreaker: circuitBreaker:
expression: foobar expression: foobar
checkPeriod: 42s checkPeriod: 42s
fallbackDuration: 42s fallbackDuration: 42s
recoveryDuration: 42s recoveryDuration: 42s
Middleware05: Middleware06:
compress: compress:
excludedContentTypes: excludedContentTypes:
- foobar - foobar
- foobar - foobar
includedContentTypes:
- foobar
- foobar
minResponseBodyBytes: 42 minResponseBodyBytes: 42
Middleware06:
contentType: {}
Middleware07: Middleware07:
contentType: {}
Middleware08:
digestAuth: digestAuth:
users: users:
- foobar - foobar
@ -151,14 +158,14 @@ http:
removeHeader: true removeHeader: true
realm: foobar realm: foobar
headerField: foobar headerField: foobar
Middleware08: Middleware09:
errors: errors:
status: status:
- foobar - foobar
- foobar - foobar
service: foobar service: foobar
query: foobar query: foobar
Middleware09: Middleware10:
forwardAuth: forwardAuth:
address: foobar address: foobar
tls: tls:
@ -174,7 +181,15 @@ http:
authRequestHeaders: authRequestHeaders:
- foobar - foobar
- foobar - foobar
Middleware10: addAuthCookiesToResponse:
- foobar
- foobar
Middleware11:
grpcWeb:
allowOrigins:
- foobar
- foobar
Middleware12:
headers: headers:
customRequestHeaders: customRequestHeaders:
name0: foobar name0: foobar
@ -223,7 +238,18 @@ http:
referrerPolicy: foobar referrerPolicy: foobar
permissionsPolicy: foobar permissionsPolicy: foobar
isDevelopment: true isDevelopment: true
Middleware11: Middleware13:
ipAllowList:
sourceRange:
- foobar
- foobar
ipStrategy:
depth: 42
excludedIPs:
- foobar
- foobar
rejectStatusCode: 42
Middleware14:
ipWhiteList: ipWhiteList:
sourceRange: sourceRange:
- foobar - foobar
@ -233,18 +259,7 @@ http:
excludedIPs: excludedIPs:
- foobar - foobar
- foobar - foobar
Middleware12: Middleware15:
ipAllowList:
rejectStatusCode: 404
sourceRange:
- foobar
- foobar
ipStrategy:
depth: 42
excludedIPs:
- foobar
- foobar
Middleware13:
inFlightReq: inFlightReq:
amount: 42 amount: 42
sourceCriterion: sourceCriterion:
@ -255,13 +270,14 @@ http:
- foobar - foobar
requestHeaderName: foobar requestHeaderName: foobar
requestHost: true requestHost: true
Middleware14: Middleware16:
passTLSClientCert: passTLSClientCert:
pem: true pem: true
info: info:
notAfter: true notAfter: true
notBefore: true notBefore: true
sans: true sans: true
serialNumber: true
subject: subject:
country: true country: true
province: true province: true
@ -279,12 +295,15 @@ http:
commonName: true commonName: true
serialNumber: true serialNumber: true
domainComponent: true domainComponent: true
serialNumber: true Middleware17:
Middleware15:
plugin: plugin:
PluginConf: PluginConf0:
foo: bar name0: foobar
Middleware16: name1: foobar
PluginConf1:
name0: foobar
name1: foobar
Middleware18:
rateLimit: rateLimit:
average: 42 average: 42
period: 42s period: 42s
@ -297,42 +316,37 @@ http:
- foobar - foobar
requestHeaderName: foobar requestHeaderName: foobar
requestHost: true requestHost: true
Middleware17: Middleware19:
redirectRegex: redirectRegex:
regex: foobar regex: foobar
replacement: foobar replacement: foobar
permanent: true permanent: true
Middleware18: Middleware20:
redirectScheme: redirectScheme:
scheme: foobar scheme: foobar
port: foobar port: foobar
permanent: true permanent: true
Middleware19: Middleware21:
replacePath: replacePath:
path: foobar path: foobar
Middleware20: Middleware22:
replacePathRegex: replacePathRegex:
regex: foobar regex: foobar
replacement: foobar replacement: foobar
Middleware21: Middleware23:
retry: retry:
attempts: 42 attempts: 42
initialInterval: 42s initialInterval: 42s
Middleware22: Middleware24:
stripPrefix: stripPrefix:
prefixes: prefixes:
- foobar - foobar
- foobar - foobar
Middleware23: Middleware25:
stripPrefixRegex: stripPrefixRegex:
regex: regex:
- foobar - foobar
- foobar - foobar
Middleware24:
grpcWeb:
allowOrigins:
- foobar
- foobar
serversTransports: serversTransports:
ServersTransport0: ServersTransport0:
serverName: foobar serverName: foobar
@ -359,7 +373,6 @@ http:
- foobar - foobar
- foobar - foobar
trustDomain: foobar trustDomain: foobar
ServersTransport1: ServersTransport1:
serverName: foobar serverName: foobar
insecureSkipVerify: true insecureSkipVerify: true
@ -385,7 +398,6 @@ http:
- foobar - foobar
- foobar - foobar
trustDomain: foobar trustDomain: foobar
tcp: tcp:
routers: routers:
TCPRouter0: TCPRouter0:
@ -437,7 +449,6 @@ tcp:
services: services:
TCPService01: TCPService01:
loadBalancer: loadBalancer:
serversTransport: foobar
proxyProtocol: proxyProtocol:
version: 42 version: 42
servers: servers:
@ -445,6 +456,7 @@ tcp:
tls: true tls: true
- address: foobar - address: foobar
tls: true tls: true
serversTransport: foobar
TCPService02: TCPService02:
weighted: weighted:
services: services:
@ -453,23 +465,23 @@ tcp:
- name: foobar - name: foobar
weight: 42 weight: 42
middlewares: middlewares:
TCPMiddleware00: TCPMiddleware01:
ipAllowList: ipAllowList:
sourceRange: sourceRange:
- foobar - foobar
- foobar - foobar
TCPMiddleware01: TCPMiddleware02:
ipWhiteList:
sourceRange:
- foobar
- foobar
TCPMiddleware03:
inFlightConn: inFlightConn:
amount: 42 amount: 42
TCPMiddleware02:
ipAllowList:
sourceRange:
- foobar
- foobar
serversTransports: serversTransports:
TCPServersTransport0: TCPServersTransport0:
dialTimeout: 42s
dialKeepAlive: 42s dialKeepAlive: 42s
dialTimeout: 42s
terminationDelay: 42s terminationDelay: 42s
tls: tls:
serverName: foobar serverName: foobar
@ -489,8 +501,8 @@ tcp:
- foobar - foobar
trustDomain: foobar trustDomain: foobar
TCPServersTransport1: TCPServersTransport1:
dialTimeout: 42s
dialKeepAlive: 42s dialKeepAlive: 42s
dialTimeout: 42s
terminationDelay: 42s terminationDelay: 42s
tls: tls:
serverName: foobar serverName: foobar

View file

@ -160,6 +160,12 @@ spec:
can be accessed by client-side APIs, such as can be accessed by client-side APIs, such as
JavaScript. JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds
until the cookie expires. When set to a negative
number, the cookie expires immediately. When
set to zero, the cookie never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
@ -750,6 +756,13 @@ spec:
items: items:
type: string type: string
type: array type: array
includedContentTypes:
description: IncludedContentTypes defines the list of content
types to compare the Content-Type header of the responses before
compressing.
items:
type: string
type: array
minResponseBodyBytes: minResponseBodyBytes:
description: 'MinResponseBodyBytes defines the minimum amount description: 'MinResponseBodyBytes defines the minimum amount
of bytes a response body must have to be compressed. Default: of bytes a response body must have to be compressed. Default:
@ -870,6 +883,12 @@ spec:
description: HTTPOnly defines whether the cookie can description: HTTPOnly defines whether the cookie can
be accessed by client-side APIs, such as JavaScript. be accessed by client-side APIs, such as JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds
until the cookie expires. When set to a negative
number, the cookie expires immediately. When set
to zero, the cookie never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
@ -912,6 +931,12 @@ spec:
This middleware delegates the request authentication to a Service. This middleware delegates the request authentication to a Service.
More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/forwardauth/' More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/forwardauth/'
properties: properties:
addAuthCookiesToResponse:
description: AddAuthCookiesToResponse defines the list of cookies
to copy from the authentication server response to the response.
items:
type: string
type: array
address: address:
description: Address defines the authentication server address. description: Address defines the authentication server address.
type: string type: string
@ -2145,6 +2170,12 @@ spec:
description: HTTPOnly defines whether the cookie description: HTTPOnly defines whether the cookie
can be accessed by client-side APIs, such as JavaScript. can be accessed by client-side APIs, such as JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds
until the cookie expires. When set to a negative
number, the cookie expires immediately. When set
to zero, the cookie never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
@ -2236,6 +2267,12 @@ spec:
description: HTTPOnly defines whether the cookie can be description: HTTPOnly defines whether the cookie can be
accessed by client-side APIs, such as JavaScript. accessed by client-side APIs, such as JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds until
the cookie expires. When set to a negative number, the
cookie expires immediately. When set to zero, the cookie
never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
@ -2343,6 +2380,12 @@ spec:
description: HTTPOnly defines whether the cookie description: HTTPOnly defines whether the cookie
can be accessed by client-side APIs, such as JavaScript. can be accessed by client-side APIs, such as JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds
until the cookie expires. When set to a negative
number, the cookie expires immediately. When set
to zero, the cookie never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
@ -2382,6 +2425,12 @@ spec:
description: HTTPOnly defines whether the cookie can be description: HTTPOnly defines whether the cookie can be
accessed by client-side APIs, such as JavaScript. accessed by client-side APIs, such as JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds until
the cookie expires. When set to a negative number, the
cookie expires immediately. When set to zero, the cookie
never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string

View file

@ -1,146 +1,157 @@
| `traefik/http/middlewares/Middleware00/addPrefix/prefix` | `foobar` | <!--
| `traefik/http/middlewares/Middleware01/basicAuth/headerField` | `foobar` | CODE GENERATED AUTOMATICALLY
| `traefik/http/middlewares/Middleware01/basicAuth/realm` | `foobar` | THIS FILE MUST NOT BE EDITED BY HAND
| `traefik/http/middlewares/Middleware01/basicAuth/removeHeader` | `true` | -->
| `traefik/http/middlewares/Middleware01/basicAuth/users/0` | `foobar` | | `traefik/http/middlewares/Middleware01/addPrefix/prefix` | `foobar` |
| `traefik/http/middlewares/Middleware01/basicAuth/users/1` | `foobar` | | `traefik/http/middlewares/Middleware02/basicAuth/headerField` | `foobar` |
| `traefik/http/middlewares/Middleware01/basicAuth/usersFile` | `foobar` | | `traefik/http/middlewares/Middleware02/basicAuth/realm` | `foobar` |
| `traefik/http/middlewares/Middleware02/buffering/maxRequestBodyBytes` | `42` | | `traefik/http/middlewares/Middleware02/basicAuth/removeHeader` | `true` |
| `traefik/http/middlewares/Middleware02/buffering/maxResponseBodyBytes` | `42` | | `traefik/http/middlewares/Middleware02/basicAuth/users/0` | `foobar` |
| `traefik/http/middlewares/Middleware02/buffering/memRequestBodyBytes` | `42` | | `traefik/http/middlewares/Middleware02/basicAuth/users/1` | `foobar` |
| `traefik/http/middlewares/Middleware02/buffering/memResponseBodyBytes` | `42` | | `traefik/http/middlewares/Middleware02/basicAuth/usersFile` | `foobar` |
| `traefik/http/middlewares/Middleware02/buffering/retryExpression` | `foobar` | | `traefik/http/middlewares/Middleware03/buffering/maxRequestBodyBytes` | `42` |
| `traefik/http/middlewares/Middleware03/chain/middlewares/0` | `foobar` | | `traefik/http/middlewares/Middleware03/buffering/maxResponseBodyBytes` | `42` |
| `traefik/http/middlewares/Middleware03/chain/middlewares/1` | `foobar` | | `traefik/http/middlewares/Middleware03/buffering/memRequestBodyBytes` | `42` |
| `traefik/http/middlewares/Middleware04/circuitBreaker/checkPeriod` | `42s` | | `traefik/http/middlewares/Middleware03/buffering/memResponseBodyBytes` | `42` |
| `traefik/http/middlewares/Middleware04/circuitBreaker/expression` | `foobar` | | `traefik/http/middlewares/Middleware03/buffering/retryExpression` | `foobar` |
| `traefik/http/middlewares/Middleware04/circuitBreaker/fallbackDuration` | `42s` | | `traefik/http/middlewares/Middleware04/chain/middlewares/0` | `foobar` |
| `traefik/http/middlewares/Middleware04/circuitBreaker/recoveryDuration` | `42s` | | `traefik/http/middlewares/Middleware04/chain/middlewares/1` | `foobar` |
| `traefik/http/middlewares/Middleware05/compress/excludedContentTypes/0` | `foobar` | | `traefik/http/middlewares/Middleware05/circuitBreaker/checkPeriod` | `42s` |
| `traefik/http/middlewares/Middleware05/compress/excludedContentTypes/1` | `foobar` | | `traefik/http/middlewares/Middleware05/circuitBreaker/expression` | `foobar` |
| `traefik/http/middlewares/Middleware05/compress/minResponseBodyBytes` | `42` | | `traefik/http/middlewares/Middleware05/circuitBreaker/fallbackDuration` | `42s` |
| `traefik/http/middlewares/Middleware06/contentType` | `` | | `traefik/http/middlewares/Middleware05/circuitBreaker/recoveryDuration` | `42s` |
| `traefik/http/middlewares/Middleware07/digestAuth/headerField` | `foobar` | | `traefik/http/middlewares/Middleware06/compress/excludedContentTypes/0` | `foobar` |
| `traefik/http/middlewares/Middleware07/digestAuth/realm` | `foobar` | | `traefik/http/middlewares/Middleware06/compress/excludedContentTypes/1` | `foobar` |
| `traefik/http/middlewares/Middleware07/digestAuth/removeHeader` | `true` | | `traefik/http/middlewares/Middleware06/compress/includedContentTypes/0` | `foobar` |
| `traefik/http/middlewares/Middleware07/digestAuth/users/0` | `foobar` | | `traefik/http/middlewares/Middleware06/compress/includedContentTypes/1` | `foobar` |
| `traefik/http/middlewares/Middleware07/digestAuth/users/1` | `foobar` | | `traefik/http/middlewares/Middleware06/compress/minResponseBodyBytes` | `42` |
| `traefik/http/middlewares/Middleware07/digestAuth/usersFile` | `foobar` | | `traefik/http/middlewares/Middleware07/contentType` | `` |
| `traefik/http/middlewares/Middleware08/errors/query` | `foobar` | | `traefik/http/middlewares/Middleware08/digestAuth/headerField` | `foobar` |
| `traefik/http/middlewares/Middleware08/errors/service` | `foobar` | | `traefik/http/middlewares/Middleware08/digestAuth/realm` | `foobar` |
| `traefik/http/middlewares/Middleware08/errors/status/0` | `foobar` | | `traefik/http/middlewares/Middleware08/digestAuth/removeHeader` | `true` |
| `traefik/http/middlewares/Middleware08/errors/status/1` | `foobar` | | `traefik/http/middlewares/Middleware08/digestAuth/users/0` | `foobar` |
| `traefik/http/middlewares/Middleware09/forwardAuth/address` | `foobar` | | `traefik/http/middlewares/Middleware08/digestAuth/users/1` | `foobar` |
| `traefik/http/middlewares/Middleware09/forwardAuth/authRequestHeaders/0` | `foobar` | | `traefik/http/middlewares/Middleware08/digestAuth/usersFile` | `foobar` |
| `traefik/http/middlewares/Middleware09/forwardAuth/authRequestHeaders/1` | `foobar` | | `traefik/http/middlewares/Middleware09/errors/query` | `foobar` |
| `traefik/http/middlewares/Middleware09/forwardAuth/authResponseHeaders/0` | `foobar` | | `traefik/http/middlewares/Middleware09/errors/service` | `foobar` |
| `traefik/http/middlewares/Middleware09/forwardAuth/authResponseHeaders/1` | `foobar` | | `traefik/http/middlewares/Middleware09/errors/status/0` | `foobar` |
| `traefik/http/middlewares/Middleware09/forwardAuth/authResponseHeadersRegex` | `foobar` | | `traefik/http/middlewares/Middleware09/errors/status/1` | `foobar` |
| `traefik/http/middlewares/Middleware09/forwardAuth/tls/ca` | `foobar` | | `traefik/http/middlewares/Middleware10/forwardAuth/addAuthCookiesToResponse/0` | `foobar` |
| `traefik/http/middlewares/Middleware09/forwardAuth/tls/cert` | `foobar` | | `traefik/http/middlewares/Middleware10/forwardAuth/addAuthCookiesToResponse/1` | `foobar` |
| `traefik/http/middlewares/Middleware09/forwardAuth/tls/insecureSkipVerify` | `true` | | `traefik/http/middlewares/Middleware10/forwardAuth/address` | `foobar` |
| `traefik/http/middlewares/Middleware09/forwardAuth/tls/key` | `foobar` | | `traefik/http/middlewares/Middleware10/forwardAuth/authRequestHeaders/0` | `foobar` |
| `traefik/http/middlewares/Middleware09/forwardAuth/trustForwardHeader` | `true` | | `traefik/http/middlewares/Middleware10/forwardAuth/authRequestHeaders/1` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowCredentials` | `true` | | `traefik/http/middlewares/Middleware10/forwardAuth/authResponseHeaders/0` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowHeaders/0` | `foobar` | | `traefik/http/middlewares/Middleware10/forwardAuth/authResponseHeaders/1` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowHeaders/1` | `foobar` | | `traefik/http/middlewares/Middleware10/forwardAuth/authResponseHeadersRegex` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowMethods/0` | `foobar` | | `traefik/http/middlewares/Middleware10/forwardAuth/tls/ca` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowMethods/1` | `foobar` | | `traefik/http/middlewares/Middleware10/forwardAuth/tls/cert` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowOriginList/0` | `foobar` | | `traefik/http/middlewares/Middleware10/forwardAuth/tls/insecureSkipVerify` | `true` |
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowOriginList/1` | `foobar` | | `traefik/http/middlewares/Middleware10/forwardAuth/tls/key` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowOriginListRegex/0` | `foobar` | | `traefik/http/middlewares/Middleware10/forwardAuth/trustForwardHeader` | `true` |
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowOriginListRegex/1` | `foobar` | | `traefik/http/middlewares/Middleware11/grpcWeb/allowOrigins/0` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/accessControlExposeHeaders/0` | `foobar` | | `traefik/http/middlewares/Middleware11/grpcWeb/allowOrigins/1` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/accessControlExposeHeaders/1` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/accessControlAllowCredentials` | `true` |
| `traefik/http/middlewares/Middleware10/headers/accessControlMaxAge` | `42` | | `traefik/http/middlewares/Middleware12/headers/accessControlAllowHeaders/0` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/addVaryHeader` | `true` | | `traefik/http/middlewares/Middleware12/headers/accessControlAllowHeaders/1` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/allowedHosts/0` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/accessControlAllowMethods/0` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/allowedHosts/1` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/accessControlAllowMethods/1` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/browserXssFilter` | `true` | | `traefik/http/middlewares/Middleware12/headers/accessControlAllowOriginList/0` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/contentSecurityPolicy` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/accessControlAllowOriginList/1` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/contentTypeNosniff` | `true` | | `traefik/http/middlewares/Middleware12/headers/accessControlAllowOriginListRegex/0` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/customBrowserXSSValue` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/accessControlAllowOriginListRegex/1` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/customFrameOptionsValue` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/accessControlExposeHeaders/0` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/customRequestHeaders/name0` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/accessControlExposeHeaders/1` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/customRequestHeaders/name1` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/accessControlMaxAge` | `42` |
| `traefik/http/middlewares/Middleware10/headers/customResponseHeaders/name0` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/addVaryHeader` | `true` |
| `traefik/http/middlewares/Middleware10/headers/customResponseHeaders/name1` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/allowedHosts/0` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/forceSTSHeader` | `true` | | `traefik/http/middlewares/Middleware12/headers/allowedHosts/1` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/frameDeny` | `true` | | `traefik/http/middlewares/Middleware12/headers/browserXssFilter` | `true` |
| `traefik/http/middlewares/Middleware10/headers/hostsProxyHeaders/0` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/contentSecurityPolicy` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/hostsProxyHeaders/1` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/contentTypeNosniff` | `true` |
| `traefik/http/middlewares/Middleware10/headers/isDevelopment` | `true` | | `traefik/http/middlewares/Middleware12/headers/customBrowserXSSValue` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/permissionsPolicy` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/customFrameOptionsValue` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/publicKey` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/customRequestHeaders/name0` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/referrerPolicy` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/customRequestHeaders/name1` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/sslProxyHeaders/name0` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/customResponseHeaders/name0` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/sslProxyHeaders/name1` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/customResponseHeaders/name1` | `foobar` |
| `traefik/http/middlewares/Middleware10/headers/stsIncludeSubdomains` | `true` | | `traefik/http/middlewares/Middleware12/headers/forceSTSHeader` | `true` |
| `traefik/http/middlewares/Middleware10/headers/stsPreload` | `true` | | `traefik/http/middlewares/Middleware12/headers/frameDeny` | `true` |
| `traefik/http/middlewares/Middleware10/headers/stsSeconds` | `42` | | `traefik/http/middlewares/Middleware12/headers/hostsProxyHeaders/0` | `foobar` |
| `traefik/http/middlewares/Middleware11/ipWhiteList/ipStrategy/depth` | `42` | | `traefik/http/middlewares/Middleware12/headers/hostsProxyHeaders/1` | `foobar` |
| `traefik/http/middlewares/Middleware11/ipWhiteList/ipStrategy/excludedIPs/0` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/isDevelopment` | `true` |
| `traefik/http/middlewares/Middleware11/ipWhiteList/ipStrategy/excludedIPs/1` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/permissionsPolicy` | `foobar` |
| `traefik/http/middlewares/Middleware11/ipWhiteList/sourceRange/0` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/publicKey` | `foobar` |
| `traefik/http/middlewares/Middleware11/ipWhiteList/sourceRange/1` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/referrerPolicy` | `foobar` |
| `traefik/http/middlewares/Middleware12/ipAllowList/ipStrategy/depth` | `42` | | `traefik/http/middlewares/Middleware12/headers/sslProxyHeaders/name0` | `foobar` |
| `traefik/http/middlewares/Middleware12/ipAllowList/ipStrategy/excludedIPs/0` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/sslProxyHeaders/name1` | `foobar` |
| `traefik/http/middlewares/Middleware12/ipAllowList/ipStrategy/excludedIPs/1` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/stsIncludeSubdomains` | `true` |
| `traefik/http/middlewares/Middleware12/ipAllowList/rejectStatusCode` | `404` | | `traefik/http/middlewares/Middleware12/headers/stsPreload` | `true` |
| `traefik/http/middlewares/Middleware12/ipAllowList/sourceRange/0` | `foobar` | | `traefik/http/middlewares/Middleware12/headers/stsSeconds` | `42` |
| `traefik/http/middlewares/Middleware12/ipAllowList/sourceRange/1` | `foobar` | | `traefik/http/middlewares/Middleware13/ipAllowList/ipStrategy/depth` | `42` |
| `traefik/http/middlewares/Middleware13/inFlightReq/amount` | `42` | | `traefik/http/middlewares/Middleware13/ipAllowList/ipStrategy/excludedIPs/0` | `foobar` |
| `traefik/http/middlewares/Middleware13/inFlightReq/sourceCriterion/ipStrategy/depth` | `42` | | `traefik/http/middlewares/Middleware13/ipAllowList/ipStrategy/excludedIPs/1` | `foobar` |
| `traefik/http/middlewares/Middleware13/inFlightReq/sourceCriterion/ipStrategy/excludedIPs/0` | `foobar` | | `traefik/http/middlewares/Middleware13/ipAllowList/rejectStatusCode` | `42` |
| `traefik/http/middlewares/Middleware13/inFlightReq/sourceCriterion/ipStrategy/excludedIPs/1` | `foobar` | | `traefik/http/middlewares/Middleware13/ipAllowList/sourceRange/0` | `foobar` |
| `traefik/http/middlewares/Middleware13/inFlightReq/sourceCriterion/requestHeaderName` | `foobar` | | `traefik/http/middlewares/Middleware13/ipAllowList/sourceRange/1` | `foobar` |
| `traefik/http/middlewares/Middleware13/inFlightReq/sourceCriterion/requestHost` | `true` | | `traefik/http/middlewares/Middleware14/ipWhiteList/ipStrategy/depth` | `42` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/issuer/commonName` | `true` | | `traefik/http/middlewares/Middleware14/ipWhiteList/ipStrategy/excludedIPs/0` | `foobar` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/issuer/country` | `true` | | `traefik/http/middlewares/Middleware14/ipWhiteList/ipStrategy/excludedIPs/1` | `foobar` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/issuer/domainComponent` | `true` | | `traefik/http/middlewares/Middleware14/ipWhiteList/sourceRange/0` | `foobar` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/issuer/locality` | `true` | | `traefik/http/middlewares/Middleware14/ipWhiteList/sourceRange/1` | `foobar` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/issuer/organization` | `true` | | `traefik/http/middlewares/Middleware15/inFlightReq/amount` | `42` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/issuer/province` | `true` | | `traefik/http/middlewares/Middleware15/inFlightReq/sourceCriterion/ipStrategy/depth` | `42` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/issuer/serialNumber` | `true` | | `traefik/http/middlewares/Middleware15/inFlightReq/sourceCriterion/ipStrategy/excludedIPs/0` | `foobar` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/notAfter` | `true` | | `traefik/http/middlewares/Middleware15/inFlightReq/sourceCriterion/ipStrategy/excludedIPs/1` | `foobar` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/notBefore` | `true` | | `traefik/http/middlewares/Middleware15/inFlightReq/sourceCriterion/requestHeaderName` | `foobar` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/sans` | `true` | | `traefik/http/middlewares/Middleware15/inFlightReq/sourceCriterion/requestHost` | `true` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/serialNumber` | `true` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/issuer/commonName` | `true` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/subject/commonName` | `true` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/issuer/country` | `true` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/subject/country` | `true` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/issuer/domainComponent` | `true` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/subject/domainComponent` | `true` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/issuer/locality` | `true` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/subject/locality` | `true` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/issuer/organization` | `true` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/subject/organization` | `true` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/issuer/province` | `true` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/subject/organizationalUnit` | `true` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/issuer/serialNumber` | `true` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/subject/province` | `true` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/notAfter` | `true` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/subject/serialNumber` | `true` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/notBefore` | `true` |
| `traefik/http/middlewares/Middleware14/passTLSClientCert/pem` | `true` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/sans` | `true` |
| `traefik/http/middlewares/Middleware15/plugin/PluginConf/foo` | `bar` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/serialNumber` | `true` |
| `traefik/http/middlewares/Middleware16/rateLimit/average` | `42` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/subject/commonName` | `true` |
| `traefik/http/middlewares/Middleware16/rateLimit/burst` | `42` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/subject/country` | `true` |
| `traefik/http/middlewares/Middleware16/rateLimit/period` | `42s` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/subject/domainComponent` | `true` |
| `traefik/http/middlewares/Middleware16/rateLimit/sourceCriterion/ipStrategy/depth` | `42` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/subject/locality` | `true` |
| `traefik/http/middlewares/Middleware16/rateLimit/sourceCriterion/ipStrategy/excludedIPs/0` | `foobar` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/subject/organization` | `true` |
| `traefik/http/middlewares/Middleware16/rateLimit/sourceCriterion/ipStrategy/excludedIPs/1` | `foobar` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/subject/organizationalUnit` | `true` |
| `traefik/http/middlewares/Middleware16/rateLimit/sourceCriterion/requestHeaderName` | `foobar` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/subject/province` | `true` |
| `traefik/http/middlewares/Middleware16/rateLimit/sourceCriterion/requestHost` | `true` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/info/subject/serialNumber` | `true` |
| `traefik/http/middlewares/Middleware17/redirectRegex/permanent` | `true` | | `traefik/http/middlewares/Middleware16/passTLSClientCert/pem` | `true` |
| `traefik/http/middlewares/Middleware17/redirectRegex/regex` | `foobar` | | `traefik/http/middlewares/Middleware17/plugin/PluginConf0/name0` | `foobar` |
| `traefik/http/middlewares/Middleware17/redirectRegex/replacement` | `foobar` | | `traefik/http/middlewares/Middleware17/plugin/PluginConf0/name1` | `foobar` |
| `traefik/http/middlewares/Middleware18/redirectScheme/permanent` | `true` | | `traefik/http/middlewares/Middleware17/plugin/PluginConf1/name0` | `foobar` |
| `traefik/http/middlewares/Middleware18/redirectScheme/port` | `foobar` | | `traefik/http/middlewares/Middleware17/plugin/PluginConf1/name1` | `foobar` |
| `traefik/http/middlewares/Middleware18/redirectScheme/scheme` | `foobar` | | `traefik/http/middlewares/Middleware18/rateLimit/average` | `42` |
| `traefik/http/middlewares/Middleware19/replacePath/path` | `foobar` | | `traefik/http/middlewares/Middleware18/rateLimit/burst` | `42` |
| `traefik/http/middlewares/Middleware20/replacePathRegex/regex` | `foobar` | | `traefik/http/middlewares/Middleware18/rateLimit/period` | `42s` |
| `traefik/http/middlewares/Middleware20/replacePathRegex/replacement` | `foobar` | | `traefik/http/middlewares/Middleware18/rateLimit/sourceCriterion/ipStrategy/depth` | `42` |
| `traefik/http/middlewares/Middleware21/retry/attempts` | `42` | | `traefik/http/middlewares/Middleware18/rateLimit/sourceCriterion/ipStrategy/excludedIPs/0` | `foobar` |
| `traefik/http/middlewares/Middleware21/retry/initialInterval` | `42s` | | `traefik/http/middlewares/Middleware18/rateLimit/sourceCriterion/ipStrategy/excludedIPs/1` | `foobar` |
| `traefik/http/middlewares/Middleware22/stripPrefix/prefixes/0` | `foobar` | | `traefik/http/middlewares/Middleware18/rateLimit/sourceCriterion/requestHeaderName` | `foobar` |
| `traefik/http/middlewares/Middleware22/stripPrefix/prefixes/1` | `foobar` | | `traefik/http/middlewares/Middleware18/rateLimit/sourceCriterion/requestHost` | `true` |
| `traefik/http/middlewares/Middleware23/stripPrefixRegex/regex/0` | `foobar` | | `traefik/http/middlewares/Middleware19/redirectRegex/permanent` | `true` |
| `traefik/http/middlewares/Middleware23/stripPrefixRegex/regex/1` | `foobar` | | `traefik/http/middlewares/Middleware19/redirectRegex/regex` | `foobar` |
| `traefik/http/middlewares/Middleware24/grpcWeb/allowOrigins/0` | `foobar` | | `traefik/http/middlewares/Middleware19/redirectRegex/replacement` | `foobar` |
| `traefik/http/middlewares/Middleware24/grpcWeb/allowOrigins/1` | `foobar` | | `traefik/http/middlewares/Middleware20/redirectScheme/permanent` | `true` |
| `traefik/http/middlewares/Middleware20/redirectScheme/port` | `foobar` |
| `traefik/http/middlewares/Middleware20/redirectScheme/scheme` | `foobar` |
| `traefik/http/middlewares/Middleware21/replacePath/path` | `foobar` |
| `traefik/http/middlewares/Middleware22/replacePathRegex/regex` | `foobar` |
| `traefik/http/middlewares/Middleware22/replacePathRegex/replacement` | `foobar` |
| `traefik/http/middlewares/Middleware23/retry/attempts` | `42` |
| `traefik/http/middlewares/Middleware23/retry/initialInterval` | `42s` |
| `traefik/http/middlewares/Middleware24/stripPrefix/prefixes/0` | `foobar` |
| `traefik/http/middlewares/Middleware24/stripPrefix/prefixes/1` | `foobar` |
| `traefik/http/middlewares/Middleware25/stripPrefixRegex/regex/0` | `foobar` |
| `traefik/http/middlewares/Middleware25/stripPrefixRegex/regex/1` | `foobar` |
| `traefik/http/routers/Router0/entryPoints/0` | `foobar` | | `traefik/http/routers/Router0/entryPoints/0` | `foobar` |
| `traefik/http/routers/Router0/entryPoints/1` | `foobar` | | `traefik/http/routers/Router0/entryPoints/1` | `foobar` |
| `traefik/http/routers/Router0/middlewares/0` | `foobar` | | `traefik/http/routers/Router0/middlewares/0` | `foobar` |
@ -209,49 +220,53 @@
| `traefik/http/serversTransports/ServersTransport1/spiffe/ids/0` | `foobar` | | `traefik/http/serversTransports/ServersTransport1/spiffe/ids/0` | `foobar` |
| `traefik/http/serversTransports/ServersTransport1/spiffe/ids/1` | `foobar` | | `traefik/http/serversTransports/ServersTransport1/spiffe/ids/1` | `foobar` |
| `traefik/http/serversTransports/ServersTransport1/spiffe/trustDomain` | `foobar` | | `traefik/http/serversTransports/ServersTransport1/spiffe/trustDomain` | `foobar` |
| `traefik/http/services/Service01/loadBalancer/healthCheck/followRedirects` | `true` | | `traefik/http/services/Service01/failover/fallback` | `foobar` |
| `traefik/http/services/Service01/loadBalancer/healthCheck/headers/name0` | `foobar` | | `traefik/http/services/Service01/failover/healthCheck` | `` |
| `traefik/http/services/Service01/loadBalancer/healthCheck/headers/name1` | `foobar` | | `traefik/http/services/Service01/failover/service` | `foobar` |
| `traefik/http/services/Service01/loadBalancer/healthCheck/hostname` | `foobar` | | `traefik/http/services/Service02/loadBalancer/healthCheck/followRedirects` | `true` |
| `traefik/http/services/Service01/loadBalancer/healthCheck/interval` | `42s` | | `traefik/http/services/Service02/loadBalancer/healthCheck/headers/name0` | `foobar` |
| `traefik/http/services/Service01/loadBalancer/healthCheck/method` | `foobar` | | `traefik/http/services/Service02/loadBalancer/healthCheck/headers/name1` | `foobar` |
| `traefik/http/services/Service01/loadBalancer/healthCheck/mode` | `foobar` | | `traefik/http/services/Service02/loadBalancer/healthCheck/hostname` | `foobar` |
| `traefik/http/services/Service01/loadBalancer/healthCheck/path` | `foobar` | | `traefik/http/services/Service02/loadBalancer/healthCheck/interval` | `42s` |
| `traefik/http/services/Service01/loadBalancer/healthCheck/port` | `42` | | `traefik/http/services/Service02/loadBalancer/healthCheck/method` | `foobar` |
| `traefik/http/services/Service01/loadBalancer/healthCheck/scheme` | `foobar` | | `traefik/http/services/Service02/loadBalancer/healthCheck/mode` | `foobar` |
| `traefik/http/services/Service01/loadBalancer/healthCheck/status` | `42` | | `traefik/http/services/Service02/loadBalancer/healthCheck/path` | `foobar` |
| `traefik/http/services/Service01/loadBalancer/healthCheck/timeout` | `42s` | | `traefik/http/services/Service02/loadBalancer/healthCheck/port` | `42` |
| `traefik/http/services/Service01/loadBalancer/passHostHeader` | `true` | | `traefik/http/services/Service02/loadBalancer/healthCheck/scheme` | `foobar` |
| `traefik/http/services/Service01/loadBalancer/responseForwarding/flushInterval` | `42s` | | `traefik/http/services/Service02/loadBalancer/healthCheck/status` | `42` |
| `traefik/http/services/Service01/loadBalancer/servers/0/url` | `foobar` | | `traefik/http/services/Service02/loadBalancer/healthCheck/timeout` | `42s` |
| `traefik/http/services/Service01/loadBalancer/servers/1/url` | `foobar` | | `traefik/http/services/Service02/loadBalancer/passHostHeader` | `true` |
| `traefik/http/services/Service01/loadBalancer/serversTransport` | `foobar` | | `traefik/http/services/Service02/loadBalancer/responseForwarding/flushInterval` | `42s` |
| `traefik/http/services/Service01/loadBalancer/sticky/cookie/httpOnly` | `true` | | `traefik/http/services/Service02/loadBalancer/servers/0/url` | `foobar` |
| `traefik/http/services/Service01/loadBalancer/sticky/cookie/name` | `foobar` | | `traefik/http/services/Service02/loadBalancer/servers/1/url` | `foobar` |
| `traefik/http/services/Service01/loadBalancer/sticky/cookie/sameSite` | `foobar` | | `traefik/http/services/Service02/loadBalancer/serversTransport` | `foobar` |
| `traefik/http/services/Service01/loadBalancer/sticky/cookie/secure` | `true` | | `traefik/http/services/Service02/loadBalancer/sticky/cookie/httpOnly` | `true` |
| `traefik/http/services/Service02/mirroring/healthCheck` | `` | | `traefik/http/services/Service02/loadBalancer/sticky/cookie/maxAge` | `42` |
| `traefik/http/services/Service02/mirroring/maxBodySize` | `42` | | `traefik/http/services/Service02/loadBalancer/sticky/cookie/name` | `foobar` |
| `traefik/http/services/Service02/mirroring/mirrors/0/name` | `foobar` | | `traefik/http/services/Service02/loadBalancer/sticky/cookie/sameSite` | `foobar` |
| `traefik/http/services/Service02/mirroring/mirrors/0/percent` | `42` | | `traefik/http/services/Service02/loadBalancer/sticky/cookie/secure` | `true` |
| `traefik/http/services/Service02/mirroring/mirrors/1/name` | `foobar` | | `traefik/http/services/Service03/mirroring/healthCheck` | `` |
| `traefik/http/services/Service02/mirroring/mirrors/1/percent` | `42` | | `traefik/http/services/Service03/mirroring/maxBodySize` | `42` |
| `traefik/http/services/Service02/mirroring/service` | `foobar` | | `traefik/http/services/Service03/mirroring/mirrors/0/name` | `foobar` |
| `traefik/http/services/Service03/weighted/healthCheck` | `` | | `traefik/http/services/Service03/mirroring/mirrors/0/percent` | `42` |
| `traefik/http/services/Service03/weighted/services/0/name` | `foobar` | | `traefik/http/services/Service03/mirroring/mirrors/1/name` | `foobar` |
| `traefik/http/services/Service03/weighted/services/0/weight` | `42` | | `traefik/http/services/Service03/mirroring/mirrors/1/percent` | `42` |
| `traefik/http/services/Service03/weighted/services/1/name` | `foobar` | | `traefik/http/services/Service03/mirroring/service` | `foobar` |
| `traefik/http/services/Service03/weighted/services/1/weight` | `42` | | `traefik/http/services/Service04/weighted/healthCheck` | `` |
| `traefik/http/services/Service03/weighted/sticky/cookie/httpOnly` | `true` | | `traefik/http/services/Service04/weighted/services/0/name` | `foobar` |
| `traefik/http/services/Service03/weighted/sticky/cookie/name` | `foobar` | | `traefik/http/services/Service04/weighted/services/0/weight` | `42` |
| `traefik/http/services/Service03/weighted/sticky/cookie/sameSite` | `foobar` | | `traefik/http/services/Service04/weighted/services/1/name` | `foobar` |
| `traefik/http/services/Service03/weighted/sticky/cookie/secure` | `true` | | `traefik/http/services/Service04/weighted/services/1/weight` | `42` |
| `traefik/http/services/Service04/failover/fallback` | `foobar` | | `traefik/http/services/Service04/weighted/sticky/cookie/httpOnly` | `true` |
| `traefik/http/services/Service04/failover/healthCheck` | `` | | `traefik/http/services/Service04/weighted/sticky/cookie/maxAge` | `42` |
| `traefik/http/services/Service04/failover/service` | `foobar` | | `traefik/http/services/Service04/weighted/sticky/cookie/name` | `foobar` |
| `traefik/tcp/middlewares/TCPMiddleware00/ipAllowList/sourceRange/0` | `foobar` | | `traefik/http/services/Service04/weighted/sticky/cookie/sameSite` | `foobar` |
| `traefik/tcp/middlewares/TCPMiddleware00/ipAllowList/sourceRange/1` | `foobar` | | `traefik/http/services/Service04/weighted/sticky/cookie/secure` | `true` |
| `traefik/tcp/middlewares/TCPMiddleware01/inFlightConn/amount` | `42` | | `traefik/tcp/middlewares/TCPMiddleware01/ipAllowList/sourceRange/0` | `foobar` |
| `traefik/tcp/middlewares/TCPMiddleware01/ipAllowList/sourceRange/1` | `foobar` |
| `traefik/tcp/middlewares/TCPMiddleware02/ipWhiteList/sourceRange/0` | `foobar` |
| `traefik/tcp/middlewares/TCPMiddleware02/ipWhiteList/sourceRange/1` | `foobar` |
| `traefik/tcp/middlewares/TCPMiddleware03/inFlightConn/amount` | `42` |
| `traefik/tcp/routers/TCPRouter0/entryPoints/0` | `foobar` | | `traefik/tcp/routers/TCPRouter0/entryPoints/0` | `foobar` |
| `traefik/tcp/routers/TCPRouter0/entryPoints/1` | `foobar` | | `traefik/tcp/routers/TCPRouter0/entryPoints/1` | `foobar` |
| `traefik/tcp/routers/TCPRouter0/middlewares/0` | `foobar` | | `traefik/tcp/routers/TCPRouter0/middlewares/0` | `foobar` |
@ -286,9 +301,6 @@
| `traefik/tcp/routers/TCPRouter1/tls/passthrough` | `true` | | `traefik/tcp/routers/TCPRouter1/tls/passthrough` | `true` |
| `traefik/tcp/serversTransports/TCPServersTransport0/dialKeepAlive` | `42s` | | `traefik/tcp/serversTransports/TCPServersTransport0/dialKeepAlive` | `42s` |
| `traefik/tcp/serversTransports/TCPServersTransport0/dialTimeout` | `42s` | | `traefik/tcp/serversTransports/TCPServersTransport0/dialTimeout` | `42s` |
| `traefik/tcp/serversTransports/TCPServersTransport0/spiffe/ids/0` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport0/spiffe/ids/1` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport0/spiffe/trustDomain` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport0/terminationDelay` | `42s` | | `traefik/tcp/serversTransports/TCPServersTransport0/terminationDelay` | `42s` |
| `traefik/tcp/serversTransports/TCPServersTransport0/tls/certificates/0/certFile` | `foobar` | | `traefik/tcp/serversTransports/TCPServersTransport0/tls/certificates/0/certFile` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport0/tls/certificates/0/keyFile` | `foobar` | | `traefik/tcp/serversTransports/TCPServersTransport0/tls/certificates/0/keyFile` | `foobar` |
@ -299,11 +311,11 @@
| `traefik/tcp/serversTransports/TCPServersTransport0/tls/rootCAs/0` | `foobar` | | `traefik/tcp/serversTransports/TCPServersTransport0/tls/rootCAs/0` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport0/tls/rootCAs/1` | `foobar` | | `traefik/tcp/serversTransports/TCPServersTransport0/tls/rootCAs/1` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport0/tls/serverName` | `foobar` | | `traefik/tcp/serversTransports/TCPServersTransport0/tls/serverName` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport0/tls/spiffe/ids/0` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport0/tls/spiffe/ids/1` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport0/tls/spiffe/trustDomain` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport1/dialKeepAlive` | `42s` | | `traefik/tcp/serversTransports/TCPServersTransport1/dialKeepAlive` | `42s` |
| `traefik/tcp/serversTransports/TCPServersTransport1/dialTimeout` | `42s` | | `traefik/tcp/serversTransports/TCPServersTransport1/dialTimeout` | `42s` |
| `traefik/tcp/serversTransports/TCPServersTransport1/spiffe/ids/0` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport1/spiffe/ids/1` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport1/spiffe/trustDomain` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport1/terminationDelay` | `42s` | | `traefik/tcp/serversTransports/TCPServersTransport1/terminationDelay` | `42s` |
| `traefik/tcp/serversTransports/TCPServersTransport1/tls/certificates/0/certFile` | `foobar` | | `traefik/tcp/serversTransports/TCPServersTransport1/tls/certificates/0/certFile` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport1/tls/certificates/0/keyFile` | `foobar` | | `traefik/tcp/serversTransports/TCPServersTransport1/tls/certificates/0/keyFile` | `foobar` |
@ -314,6 +326,9 @@
| `traefik/tcp/serversTransports/TCPServersTransport1/tls/rootCAs/0` | `foobar` | | `traefik/tcp/serversTransports/TCPServersTransport1/tls/rootCAs/0` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport1/tls/rootCAs/1` | `foobar` | | `traefik/tcp/serversTransports/TCPServersTransport1/tls/rootCAs/1` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport1/tls/serverName` | `foobar` | | `traefik/tcp/serversTransports/TCPServersTransport1/tls/serverName` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport1/tls/spiffe/ids/0` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport1/tls/spiffe/ids/1` | `foobar` |
| `traefik/tcp/serversTransports/TCPServersTransport1/tls/spiffe/trustDomain` | `foobar` |
| `traefik/tcp/services/TCPService01/loadBalancer/proxyProtocol/version` | `42` | | `traefik/tcp/services/TCPService01/loadBalancer/proxyProtocol/version` | `42` |
| `traefik/tcp/services/TCPService01/loadBalancer/servers/0/address` | `foobar` | | `traefik/tcp/services/TCPService01/loadBalancer/servers/0/address` | `foobar` |
| `traefik/tcp/services/TCPService01/loadBalancer/servers/0/tls` | `true` | | `traefik/tcp/services/TCPService01/loadBalancer/servers/0/tls` | `true` |

View file

@ -160,6 +160,12 @@ spec:
can be accessed by client-side APIs, such as can be accessed by client-side APIs, such as
JavaScript. JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds
until the cookie expires. When set to a negative
number, the cookie expires immediately. When
set to zero, the cookie never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string

View file

@ -175,6 +175,13 @@ spec:
items: items:
type: string type: string
type: array type: array
includedContentTypes:
description: IncludedContentTypes defines the list of content
types to compare the Content-Type header of the responses before
compressing.
items:
type: string
type: array
minResponseBodyBytes: minResponseBodyBytes:
description: 'MinResponseBodyBytes defines the minimum amount description: 'MinResponseBodyBytes defines the minimum amount
of bytes a response body must have to be compressed. Default: of bytes a response body must have to be compressed. Default:
@ -295,6 +302,12 @@ spec:
description: HTTPOnly defines whether the cookie can description: HTTPOnly defines whether the cookie can
be accessed by client-side APIs, such as JavaScript. be accessed by client-side APIs, such as JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds
until the cookie expires. When set to a negative
number, the cookie expires immediately. When set
to zero, the cookie never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
@ -337,6 +350,12 @@ spec:
This middleware delegates the request authentication to a Service. This middleware delegates the request authentication to a Service.
More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/forwardauth/' More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/forwardauth/'
properties: properties:
addAuthCookiesToResponse:
description: AddAuthCookiesToResponse defines the list of cookies
to copy from the authentication server response to the response.
items:
type: string
type: array
address: address:
description: Address defines the authentication server address. description: Address defines the authentication server address.
type: string type: string

View file

@ -134,6 +134,12 @@ spec:
description: HTTPOnly defines whether the cookie description: HTTPOnly defines whether the cookie
can be accessed by client-side APIs, such as JavaScript. can be accessed by client-side APIs, such as JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds
until the cookie expires. When set to a negative
number, the cookie expires immediately. When set
to zero, the cookie never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
@ -225,6 +231,12 @@ spec:
description: HTTPOnly defines whether the cookie can be description: HTTPOnly defines whether the cookie can be
accessed by client-side APIs, such as JavaScript. accessed by client-side APIs, such as JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds until
the cookie expires. When set to a negative number, the
cookie expires immediately. When set to zero, the cookie
never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
@ -332,6 +344,12 @@ spec:
description: HTTPOnly defines whether the cookie description: HTTPOnly defines whether the cookie
can be accessed by client-side APIs, such as JavaScript. can be accessed by client-side APIs, such as JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds
until the cookie expires. When set to a negative
number, the cookie expires immediately. When set
to zero, the cookie never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
@ -371,6 +389,12 @@ spec:
description: HTTPOnly defines whether the cookie can be description: HTTPOnly defines whether the cookie can be
accessed by client-side APIs, such as JavaScript. accessed by client-side APIs, such as JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds until
the cookie expires. When set to a negative number, the
cookie expires immediately. When set to zero, the cookie
never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string

View file

@ -1,3 +1,5 @@
## CODE GENERATED AUTOMATICALLY
## THIS FILE MUST NOT BE EDITED BY HAND
[global] [global]
checkNewVersion = true checkNewVersion = true
sendAnonymousUsage = true sendAnonymousUsage = true
@ -6,26 +8,21 @@
insecureSkipVerify = true insecureSkipVerify = true
rootCAs = ["foobar", "foobar"] rootCAs = ["foobar", "foobar"]
maxIdleConnsPerHost = 42 maxIdleConnsPerHost = 42
[serversTransport.forwardingTimeouts] [serversTransport.forwardingTimeouts]
dialTimeout = "42s" dialTimeout = "42s"
responseHeaderTimeout = "42s" responseHeaderTimeout = "42s"
idleConnTimeout = "42s" idleConnTimeout = "42s"
readIdleTimeout = "42s"
pingTimeout = "42s"
[serversTransport.spiffe] [serversTransport.spiffe]
ids = ["foobar", "foobar"] ids = ["foobar", "foobar"]
trustDomain = "foobar" trustDomain = "foobar"
[tcpServersTransport] [tcpServersTransport]
dialTimeout = "42s"
dialKeepAlive = "42s" dialKeepAlive = "42s"
dialTimeout = "42s"
terminationDelay = "42s"
[tcpServersTransport.tls] [tcpServersTransport.tls]
insecureSkipVerify = true insecureSkipVerify = true
rootCAs = ["foobar", "foobar"] rootCAs = ["foobar", "foobar"]
[tcpServersTransport.tls.spiffe] [tcpServersTransport.tls.spiffe]
ids = ["foobar", "foobar"] ids = ["foobar", "foobar"]
trustDomain = "foobar" trustDomain = "foobar"
@ -35,8 +32,8 @@
address = "foobar" address = "foobar"
asDefault = true asDefault = true
[entryPoints.EntryPoint0.transport] [entryPoints.EntryPoint0.transport]
keepAliveMaxRequests = 42
keepAliveMaxTime = "42s" keepAliveMaxTime = "42s"
keepAliveMaxRequests = 42
[entryPoints.EntryPoint0.transport.lifeCycle] [entryPoints.EntryPoint0.transport.lifeCycle]
requestAcceptGraceTimeout = "42s" requestAcceptGraceTimeout = "42s"
graceTimeOut = "42s" graceTimeOut = "42s"
@ -80,31 +77,31 @@
[providers] [providers]
providersThrottleDuration = "42s" providersThrottleDuration = "42s"
[providers.docker] [providers.docker]
constraints = "foobar"
watch = true
endpoint = "foobar"
defaultRule = "foobar"
exposedByDefault = true exposedByDefault = true
useBindPortIP = true constraints = "foobar"
network = "foobar"
httpClientTimeout = "42s"
allowEmptyServices = true allowEmptyServices = true
network = "foobar"
useBindPortIP = true
watch = true
defaultRule = "foobar"
endpoint = "foobar"
httpClientTimeout = "42s"
[providers.docker.tls] [providers.docker.tls]
ca = "foobar" ca = "foobar"
cert = "foobar" cert = "foobar"
key = "foobar" key = "foobar"
insecureSkipVerify = true insecureSkipVerify = true
[providers.swarm] [providers.swarm]
constraints = "foobar"
watch = true
endpoint = "foobar"
defaultRule = "foobar"
exposedByDefault = true exposedByDefault = true
useBindPortIP = true constraints = "foobar"
network = "foobar"
refreshSeconds = "42s"
httpClientTimeout = "42s"
allowEmptyServices = true allowEmptyServices = true
network = "foobar"
useBindPortIP = true
watch = true
defaultRule = "foobar"
endpoint = "foobar"
httpClientTimeout = "42s"
refreshSeconds = "42s"
[providers.swarm.tls] [providers.swarm.tls]
ca = "foobar" ca = "foobar"
cert = "foobar" cert = "foobar"
@ -183,9 +180,9 @@
constraints = "foobar" constraints = "foobar"
prefix = "foobar" prefix = "foobar"
stale = true stale = true
namespaces = ["foobar", "foobar"]
exposedByDefault = true exposedByDefault = true
refreshInterval = "42s" refreshInterval = "42s"
namespaces = ["foobar", "foobar"]
[providers.nomad.endpoint] [providers.nomad.endpoint]
address = "foobar" address = "foobar"
region = "foobar" region = "foobar"
@ -203,11 +200,11 @@
defaultRule = "foobar" defaultRule = "foobar"
clusters = ["foobar", "foobar"] clusters = ["foobar", "foobar"]
autoDiscoverClusters = true autoDiscoverClusters = true
healthyTasksOnly = true
ecsAnywhere = true
region = "foobar" region = "foobar"
accessKeyID = "foobar" accessKeyID = "foobar"
secretAccessKey = "foobar" secretAccessKey = "foobar"
ecsAnywhere = true
healthyTasksOnly = true
[providers.consul] [providers.consul]
rootKey = "foobar" rootKey = "foobar"
endpoints = ["foobar", "foobar"] endpoints = ["foobar", "foobar"]
@ -265,14 +262,18 @@
key = "foobar" key = "foobar"
insecureSkipVerify = true insecureSkipVerify = true
[providers.plugin] [providers.plugin]
[providers.plugin.Descriptor0] [providers.plugin.PluginConf0]
[providers.plugin.Descriptor1] name0 = "foobar"
name1 = "foobar"
[providers.plugin.PluginConf1]
name0 = "foobar"
name1 = "foobar"
[api] [api]
insecure = true insecure = true
dashboard = true dashboard = true
debug = true debug = true
disabledashboardad = false disableDashboardAd = true
[metrics] [metrics]
[metrics.prometheus] [metrics.prometheus]
@ -283,8 +284,8 @@
entryPoint = "foobar" entryPoint = "foobar"
manualRouting = true manualRouting = true
[metrics.prometheus.headerLabels] [metrics.prometheus.headerLabels]
label1 = "foobar" name0 = "foobar"
label2 = "foobar" name1 = "foobar"
[metrics.datadog] [metrics.datadog]
address = "foobar" address = "foobar"
pushInterval = "42s" pushInterval = "42s"
@ -316,20 +317,19 @@
addEntryPointsLabels = true addEntryPointsLabels = true
addRoutersLabels = true addRoutersLabels = true
addServicesLabels = true addServicesLabels = true
pushInterval = "42s"
path = "foobar"
explicitBoundaries = [42.0, 42.0] explicitBoundaries = [42.0, 42.0]
insecure = true insecure = true
path = "foobar"
pushInterval = "42s"
[metrics.openTelemetry.grpc]
[metrics.openTelemetry.headers] [metrics.openTelemetry.headers]
name0 = "foobar" name0 = "foobar"
name1 = "foobar" name1 = "foobar"
[metrics.openTelemetry.tls] [metrics.openTelemetry.tls]
ca = "foobar" ca = "foobar"
caOptional = true
cert = "foobar" cert = "foobar"
insecureSkipVerify = true
key = "foobar" key = "foobar"
[metrics.openTelemetry.grpc] insecureSkipVerify = true
[ping] [ping]
entryPoint = "foobar" entryPoint = "foobar"
@ -342,8 +342,8 @@
noColor = true noColor = true
filePath = "foobar" filePath = "foobar"
maxSize = 42 maxSize = 42
maxBackups = 42
maxAge = 42 maxAge = 42
maxBackups = 42
compress = true compress = true
[accessLog] [accessLog]
@ -367,13 +367,14 @@
[tracing] [tracing]
serviceName = "foobar" serviceName = "foobar"
sampleRate = 42 sampleRate = 42.0
[tracing.headers] [tracing.headers]
header1 = "foobar" name0 = "foobar"
header2 = "foobar" name1 = "foobar"
[tracing.globalAttributes] [tracing.globalAttributes]
attr1 = "foobar" name0 = "foobar"
attr2 = "foobar" name1 = "foobar"
[tracing.otlp]
[tracing.otlp.grpc] [tracing.otlp.grpc]
endpoint = "foobar" endpoint = "foobar"
insecure = true insecure = true
@ -415,6 +416,26 @@
[certificatesResolvers.CertificateResolver0.acme.httpChallenge] [certificatesResolvers.CertificateResolver0.acme.httpChallenge]
entryPoint = "foobar" entryPoint = "foobar"
[certificatesResolvers.CertificateResolver0.acme.tlsChallenge] [certificatesResolvers.CertificateResolver0.acme.tlsChallenge]
[certificatesResolvers.CertificateResolver0.tailscale]
[certificatesResolvers.CertificateResolver1]
[certificatesResolvers.CertificateResolver1.acme]
email = "foobar"
caServer = "foobar"
preferredChain = "foobar"
storage = "foobar"
keyType = "foobar"
certificatesDuration = 42
[certificatesResolvers.CertificateResolver1.acme.eab]
kid = "foobar"
hmacEncoded = "foobar"
[certificatesResolvers.CertificateResolver1.acme.dnsChallenge]
provider = "foobar"
delayBeforeCheck = "42s"
resolvers = ["foobar", "foobar"]
disablePropagationCheck = true
[certificatesResolvers.CertificateResolver1.acme.httpChallenge]
entryPoint = "foobar"
[certificatesResolvers.CertificateResolver1.acme.tlsChallenge]
[certificatesResolvers.CertificateResolver1.tailscale] [certificatesResolvers.CertificateResolver1.tailscale]
[experimental] [experimental]
@ -427,7 +448,10 @@
moduleName = "foobar" moduleName = "foobar"
version = "foobar" version = "foobar"
[experimental.localPlugins] [experimental.localPlugins]
[experimental.localPlugins.Descriptor0] [experimental.localPlugins.LocalDescriptor0]
moduleName = "foobar" moduleName = "foobar"
[experimental.localPlugins.Descriptor1] [experimental.localPlugins.LocalDescriptor1]
moduleName = "foobar" moduleName = "foobar"
[spiffe]
workloadAPIAddr = "foobar"

View file

@ -1,7 +1,9 @@
## CODE GENERATED AUTOMATICALLY
## THIS FILE MUST NOT BE EDITED BY HAND
global: global:
checkNewVersion: true checkNewVersion: true
sendAnonymousUsage: true sendAnonymousUsage: true
serversTransports: serversTransport:
insecureSkipVerify: true insecureSkipVerify: true
rootCAs: rootCAs:
- foobar - foobar
@ -11,16 +13,15 @@ serversTransports:
dialTimeout: 42s dialTimeout: 42s
responseHeaderTimeout: 42s responseHeaderTimeout: 42s
idleConnTimeout: 42s idleConnTimeout: 42s
readIdleTimeout: 42s
pingTimeout: 42s
spiffe: spiffe:
ids: ids:
- foobar - foobar
- foobar - foobar
trustDomain: foobar trustDomain: foobar
tcpServersTransport: tcpServersTransport:
dialTimeout: 42s
dialKeepAlive: 42s dialKeepAlive: 42s
dialTimeout: 42s
terminationDelay: 42s
tls: tls:
insecureSkipVerify: true insecureSkipVerify: true
rootCAs: rootCAs:
@ -36,8 +37,6 @@ entryPoints:
address: foobar address: foobar
asDefault: true asDefault: true
transport: transport:
keepAliveMaxRequests: 42
keepAliveMaxTime: 42s
lifeCycle: lifeCycle:
requestAcceptGraceTimeout: 42s requestAcceptGraceTimeout: 42s
graceTimeOut: 42s graceTimeOut: 42s
@ -45,6 +44,8 @@ entryPoints:
readTimeout: 42s readTimeout: 42s
writeTimeout: 42s writeTimeout: 42s
idleTimeout: 42s idleTimeout: 42s
keepAliveMaxTime: 42s
keepAliveMaxRequests: 42
proxyProtocol: proxyProtocol:
insecure: true insecure: true
trustedIPs: trustedIPs:
@ -56,7 +57,6 @@ entryPoints:
- foobar - foobar
- foobar - foobar
http: http:
encodeQuerySemicolons: true
redirections: redirections:
entryPoint: entryPoint:
to: foobar to: foobar
@ -78,6 +78,7 @@ entryPoints:
sans: sans:
- foobar - foobar
- foobar - foobar
encodeQuerySemicolons: true
http2: http2:
maxConcurrentStreams: 42 maxConcurrentStreams: 42
http3: http3:
@ -87,36 +88,36 @@ entryPoints:
providers: providers:
providersThrottleDuration: 42s providersThrottleDuration: 42s
docker: docker:
exposedByDefault: true
constraints: foobar constraints: foobar
allowEmptyServices: true
network: foobar
useBindPortIP: true
watch: true watch: true
endpoint: foobar
defaultRule: foobar defaultRule: foobar
endpoint: foobar
tls: tls:
ca: foobar ca: foobar
cert: foobar cert: foobar
key: foobar key: foobar
insecureSkipVerify: true insecureSkipVerify: true
exposedByDefault: true
useBindPortIP: true
network: foobar
httpClientTimeout: 42s httpClientTimeout: 42s
allowEmptyServices: true
swarm: swarm:
exposedByDefault: true
constraints: foobar constraints: foobar
allowEmptyServices: true
network: foobar
useBindPortIP: true
watch: true watch: true
endpoint: foobar
defaultRule: foobar defaultRule: foobar
endpoint: foobar
tls: tls:
ca: foobar ca: foobar
cert: foobar cert: foobar
key: foobar key: foobar
insecureSkipVerify: true insecureSkipVerify: true
exposedByDefault: true
useBindPortIP: true
network: foobar
refreshSeconds: 42s
httpClientTimeout: 42s httpClientTimeout: 42s
allowEmptyServices: true refreshSeconds: 42s
file: file:
directory: foobar directory: foobar
watch: true watch: true
@ -131,14 +132,14 @@ providers:
- foobar - foobar
labelSelector: foobar labelSelector: foobar
ingressClass: foobar ingressClass: foobar
throttleDuration: 42s
allowEmptyServices: true
allowExternalNameServices: true
disableIngressClassLookup: true
ingressEndpoint: ingressEndpoint:
ip: foobar ip: foobar
hostname: foobar hostname: foobar
publishedService: foobar publishedService: foobar
throttleDuration: 42s
allowEmptyServices: true
allowExternalNameServices: true
disableIngressClassLookup: true
kubernetesCRD: kubernetesCRD:
endpoint: foobar endpoint: foobar
token: foobar token: foobar
@ -165,6 +166,20 @@ providers:
insecure: true insecure: true
consulCatalog: consulCatalog:
constraints: foobar constraints: foobar
endpoint:
address: foobar
scheme: foobar
datacenter: foobar
token: foobar
tls:
ca: foobar
cert: foobar
key: foobar
insecureSkipVerify: true
httpAuth:
username: foobar
password: foobar
endpointWaitTime: 42s
prefix: foobar prefix: foobar
refreshInterval: 42s refreshInterval: 42s
requireConsistent: true requireConsistent: true
@ -179,40 +194,26 @@ providers:
namespaces: namespaces:
- foobar - foobar
- foobar - foobar
endpoint:
address: foobar
scheme: foobar
datacenter: foobar
token: foobar
endpointWaitTime: 42s
tls:
ca: foobar
cert: foobar
key: foobar
insecureSkipVerify: true
httpAuth:
username: foobar
password: foobar
nomad: nomad:
defaultRule: foobar defaultRule: foobar
constraints: foobar constraints: foobar
prefix: foobar
stale: true
namespaces:
- foobar
- foobar
exposedByDefault: true
refreshInterval: 42s
endpoint: endpoint:
address: foobar address: foobar
region: foobar region: foobar
token: foobar token: foobar
endpointWaitTime: 42s
tls: tls:
ca: foobar ca: foobar
cert: foobar cert: foobar
key: foobar key: foobar
insecureSkipVerify: true insecureSkipVerify: true
endpointWaitTime: 42s
prefix: foobar
stale: true
exposedByDefault: true
refreshInterval: 42s
namespaces:
- foobar
- foobar
ecs: ecs:
constraints: foobar constraints: foobar
exposedByDefault: true exposedByDefault: true
@ -222,37 +223,37 @@ providers:
- foobar - foobar
- foobar - foobar
autoDiscoverClusters: true autoDiscoverClusters: true
healthyTasksOnly: true
ecsAnywhere: true
region: foobar region: foobar
accessKeyID: foobar accessKeyID: foobar
secretAccessKey: foobar secretAccessKey: foobar
ecsAnywhere: true
healthyTasksOnly: true
consul: consul:
rootKey: foobar rootKey: foobar
endpoints: endpoints:
- foobar - foobar
- foobar - foobar
token: foobar token: foobar
namespaces:
- foobar
- foobar
tls: tls:
ca: foobar ca: foobar
cert: foobar cert: foobar
key: foobar key: foobar
insecureSkipVerify: true insecureSkipVerify: true
namespaces:
- foobar
- foobar
etcd: etcd:
rootKey: foobar rootKey: foobar
endpoints: endpoints:
- foobar - foobar
- foobar - foobar
username: foobar
password: foobar
tls: tls:
ca: foobar ca: foobar
cert: foobar cert: foobar
key: foobar key: foobar
insecureSkipVerify: true insecureSkipVerify: true
username: foobar
password: foobar
zooKeeper: zooKeeper:
rootKey: foobar rootKey: foobar
endpoints: endpoints:
@ -265,14 +266,14 @@ providers:
endpoints: endpoints:
- foobar - foobar
- foobar - foobar
username: foobar
password: foobar
db: 42
tls: tls:
ca: foobar ca: foobar
cert: foobar cert: foobar
key: foobar key: foobar
insecureSkipVerify: true insecureSkipVerify: true
username: foobar
password: foobar
db: 42
sentinel: sentinel:
masterName: foobar masterName: foobar
username: foobar username: foobar
@ -294,13 +295,17 @@ providers:
key: foobar key: foobar
insecureSkipVerify: true insecureSkipVerify: true
plugin: plugin:
Descriptor0: {} PluginConf0:
Descriptor1: {} name0: foobar
name1: foobar
PluginConf1:
name0: foobar
name1: foobar
api: api:
insecure: true insecure: true
dashboard: true dashboard: true
debug: true debug: true
disabledashboardad: false disableDashboardAd: true
metrics: metrics:
prometheus: prometheus:
buckets: buckets:
@ -312,8 +317,8 @@ metrics:
entryPoint: foobar entryPoint: foobar
manualRouting: true manualRouting: true
headerLabels: headerLabels:
label1: foobar name0: foobar
label2: foobar name1: foobar
datadog: datadog:
address: foobar address: foobar
pushInterval: 42s pushInterval: 42s
@ -341,6 +346,7 @@ metrics:
name0: foobar name0: foobar
name1: foobar name1: foobar
openTelemetry: openTelemetry:
grpc: {}
address: foobar address: foobar
addEntryPointsLabels: true addEntryPointsLabels: true
addRoutersLabels: true addRoutersLabels: true
@ -356,12 +362,9 @@ metrics:
pushInterval: 42s pushInterval: 42s
tls: tls:
ca: foobar ca: foobar
caOptional: true
cert: foobar cert: foobar
insecureSkipVerify: true
key: foobar key: foobar
grpc: {} insecureSkipVerify: true
ping: ping:
entryPoint: foobar entryPoint: foobar
manualRouting: true manualRouting: true
@ -372,8 +375,8 @@ log:
noColor: true noColor: true
filePath: foobar filePath: foobar
maxSize: 42 maxSize: 42
maxBackups: 42
maxAge: 42 maxAge: 42
maxBackups: 42
compress: true compress: true
accessLog: accessLog:
filePath: foobar filePath: foobar
@ -397,13 +400,13 @@ accessLog:
bufferingSize: 42 bufferingSize: 42
tracing: tracing:
serviceName: foobar serviceName: foobar
sampleRate: 42
headers: headers:
header1: foobar name0: foobar
header2: foobar name1: foobar
globalAttributes: globalAttributes:
attr1: foobar name0: foobar
attr2: foobar name1: foobar
sampleRate: 42
otlp: otlp:
grpc: grpc:
endpoint: foobar endpoint: foobar
@ -429,13 +432,13 @@ certificatesResolvers:
acme: acme:
email: foobar email: foobar
caServer: foobar caServer: foobar
certificatesDuration: 42
preferredChain: foobar preferredChain: foobar
storage: foobar storage: foobar
keyType: foobar keyType: foobar
eab: eab:
kid: foobar kid: foobar
hmacEncoded: foobar hmacEncoded: foobar
certificatesDuration: 42
dnsChallenge: dnsChallenge:
provider: foobar provider: foobar
delayBeforeCheck: 42s delayBeforeCheck: 42s
@ -446,10 +449,30 @@ certificatesResolvers:
httpChallenge: httpChallenge:
entryPoint: foobar entryPoint: foobar
tlsChallenge: {} tlsChallenge: {}
tailscale: {}
CertificateResolver1: CertificateResolver1:
acme:
email: foobar
caServer: foobar
preferredChain: foobar
storage: foobar
keyType: foobar
eab:
kid: foobar
hmacEncoded: foobar
certificatesDuration: 42
dnsChallenge:
provider: foobar
delayBeforeCheck: 42s
resolvers:
- foobar
- foobar
disablePropagationCheck: true
httpChallenge:
entryPoint: foobar
tlsChallenge: {}
tailscale: {} tailscale: {}
experimental: experimental:
kubernetesGateway: true
plugins: plugins:
Descriptor0: Descriptor0:
moduleName: foobar moduleName: foobar
@ -458,7 +481,10 @@ experimental:
moduleName: foobar moduleName: foobar
version: foobar version: foobar
localPlugins: localPlugins:
Descriptor0: LocalDescriptor0:
moduleName: foobar moduleName: foobar
Descriptor1: LocalDescriptor1:
moduleName: foobar moduleName: foobar
kubernetesGateway: true
spiffe:
workloadAPIAddr: foobar

View file

@ -273,6 +273,14 @@ you'd add the tag `traefik.http.services.{name-of-your-choice}.loadbalancer.pass
traefik.http.services.myservice.loadbalancer.sticky.cookie.samesite=none traefik.http.services.myservice.loadbalancer.sticky.cookie.samesite=none
``` ```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.maxage`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```yaml
traefik.http.services.myservice.loadbalancer.sticky.cookie.maxage=42
```
??? info "`traefik.http.services.<service_name>.loadbalancer.responseforwarding.flushinterval`" ??? info "`traefik.http.services.<service_name>.loadbalancer.responseforwarding.flushinterval`"
See [response forwarding](../services/index.md#response-forwarding) for more information. See [response forwarding](../services/index.md#response-forwarding) for more information.

View file

@ -376,6 +376,14 @@ you'd add the label `traefik.http.services.<name-of-your-choice>.loadbalancer.pa
- "traefik.http.services.myservice.loadbalancer.sticky.cookie.samesite=none" - "traefik.http.services.myservice.loadbalancer.sticky.cookie.samesite=none"
``` ```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.maxage`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.sticky.cookie.maxage=42"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.responseforwarding.flushinterval`" ??? info "`traefik.http.services.<service_name>.loadbalancer.responseforwarding.flushinterval`"
See [response forwarding](../services/index.md#response-forwarding) for more information. See [response forwarding](../services/index.md#response-forwarding) for more information.

View file

@ -275,6 +275,14 @@ you'd add the label `traefik.http.services.{name-of-your-choice}.loadbalancer.pa
traefik.http.services.myservice.loadbalancer.sticky.cookie.samesite=none traefik.http.services.myservice.loadbalancer.sticky.cookie.samesite=none
``` ```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.maxage`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```yaml
traefik.http.services.myservice.loadbalancer.sticky.cookie.maxage=42
```
??? info "`traefik.http.services.<service_name>.loadbalancer.responseforwarding.flushinterval`" ??? info "`traefik.http.services.<service_name>.loadbalancer.responseforwarding.flushinterval`"
See [response forwarding](../services/index.md#response-forwarding) for more information. See [response forwarding](../services/index.md#response-forwarding) for more information.

View file

@ -348,6 +348,7 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne
name: cookie name: cookie
secure: true secure: true
sameSite: none sameSite: none
maxAge: 42
strategy: RoundRobin strategy: RoundRobin
weight: 10 weight: 10
nativeLB: true # [11] nativeLB: true # [11]

View file

@ -351,6 +351,14 @@ which in turn will create the resulting routers, services, handlers, etc.
traefik.ingress.kubernetes.io/service.sticky.cookie.httponly: "true" traefik.ingress.kubernetes.io/service.sticky.cookie.httponly: "true"
``` ```
??? info "`traefik.ingress.kubernetes.io/service.sticky.cookie.maxage`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```yaml
traefik.ingress.kubernetes.io/service.sticky.cookie.maxage: 42
```
## Path Types on Kubernetes 1.18+ ## Path Types on Kubernetes 1.18+
If the Kubernetes cluster version is 1.18+, If the Kubernetes cluster version is 1.18+,

View file

@ -244,6 +244,14 @@ A Story of key & values
|-----------------------------------------------------------------------|--------| |-----------------------------------------------------------------------|--------|
| `traefik/http/services/myservice/loadbalancer/sticky/cookie/samesite` | `none` | | `traefik/http/services/myservice/loadbalancer/sticky/cookie/samesite` | `none` |
??? info "`traefik/http/services/<service_name>/loadbalancer/sticky/cookie/maxage`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
| Key (Path) | Value |
|---------------------------------------------------------------------|-------|
| `traefik/http/services/myservice/loadbalancer/sticky/cookie/maxage` | `42` |
??? info "`traefik/http/services/<service_name>/loadbalancer/responseforwarding/flushinterval`" ??? info "`traefik/http/services/<service_name>/loadbalancer/responseforwarding/flushinterval`"
See [response forwarding](../services/index.md#response-forwarding) for more information. See [response forwarding](../services/index.md#response-forwarding) for more information.
@ -306,6 +314,12 @@ A Story of key & values
|------------------------------------------------------------------------|--------| |------------------------------------------------------------------------|--------|
| `traefik/http/services/<service_name>/weighted/sticky/cookie/httpOnly` | `true` | | `traefik/http/services/<service_name>/weighted/sticky/cookie/httpOnly` | `true` |
??? info "`traefik/http/services/<service_name>/weighted/sticky/cookie/maxage`"
| Key (Path) | Value |
|----------------------------------------------------------------------|-------|
| `traefik/http/services/<service_name>/weighted/sticky/cookie/maxage` | `42` |
### Middleware ### Middleware
More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md). More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md).

View file

@ -265,6 +265,14 @@ you'd add the tag `traefik.http.services.{name-of-your-choice}.loadbalancer.pass
traefik.http.services.myservice.loadbalancer.sticky.cookie.samesite=none traefik.http.services.myservice.loadbalancer.sticky.cookie.samesite=none
``` ```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.maxage`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```yaml
traefik.http.services.myservice.loadbalancer.sticky.cookie.maxage=42
```
??? info "`traefik.http.services.<service_name>.loadbalancer.responseforwarding.flushinterval`" ??? info "`traefik.http.services.<service_name>.loadbalancer.responseforwarding.flushinterval`"
See [response forwarding](../services/index.md#response-forwarding) for more information. See [response forwarding](../services/index.md#response-forwarding) for more information.

View file

@ -187,6 +187,13 @@ On subsequent requests, to keep the session alive with the same server, the clie
The default cookie name is an abbreviation of a sha1 (ex: `_1d52e`). The default cookie name is an abbreviation of a sha1 (ex: `_1d52e`).
!!! info "MaxAge"
By default, the affinity cookie will never expire as the `MaxAge` option is set to zero.
This option indicates the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately.
!!! info "Secure & HTTPOnly & SameSite flags" !!! info "Secure & HTTPOnly & SameSite flags"
By default, the affinity cookie is created without those flags. By default, the affinity cookie is created without those flags.

View file

@ -1,47 +0,0 @@
# WEBUI
FROM node:12.11 as webui
ENV WEBUI_DIR /src/webui
RUN mkdir -p $WEBUI_DIR
COPY ./webui/ $WEBUI_DIR/
WORKDIR $WEBUI_DIR
RUN yarn install
RUN yarn build
# BUILD
FROM golang:1.21-alpine as gobuild
RUN apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \
&& update-ca-certificates \
&& rm -rf /var/cache/apk/*
WORKDIR /go/src/github.com/traefik/traefik
# Download go modules
COPY go.mod .
COPY go.sum .
RUN GO111MODULE=on GOPROXY=https://proxy.golang.org go mod download
COPY . /go/src/github.com/traefik/traefik
RUN rm -rf /go/src/github.com/traefik/traefik/webui/static/
COPY --from=webui /src/webui/static/ /go/src/github.com/traefik/traefik/webui/static/
RUN ./script/make.sh generate binary
## IMAGE
FROM alpine:3.14
RUN apk --no-cache --no-progress add bash curl ca-certificates tzdata \
&& update-ca-certificates \
&& rm -rf /var/cache/apk/*
COPY --from=gobuild /go/src/github.com/traefik/traefik/dist/traefik /
EXPOSE 80
VOLUME ["/tmp"]
ENTRYPOINT ["/traefik"]

4
go.mod
View file

@ -28,7 +28,7 @@ require (
github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-retryablehttp v0.7.4 github.com/hashicorp/go-retryablehttp v0.7.4
github.com/hashicorp/go-version v1.6.0 github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/nomad/api v0.0.0-20220506174431-b5665129cd1f github.com/hashicorp/nomad/api v0.0.0-20231213195942-64e3dca9274b
github.com/http-wasm/http-wasm-host-go v0.5.2 github.com/http-wasm/http-wasm-host-go v0.5.2
github.com/influxdata/influxdb-client-go/v2 v2.7.0 github.com/influxdata/influxdb-client-go/v2 v2.7.0
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d
@ -196,7 +196,7 @@ require (
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae // indirect github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae // indirect
github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
github.com/hashicorp/cronexpr v1.1.1 // indirect github.com/hashicorp/cronexpr v1.1.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect

13
go.sum
View file

@ -311,6 +311,8 @@ github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
@ -538,8 +540,8 @@ github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyN
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/consul/sdk v0.15.0 h1:2qK9nDrr4tiJKRoxPGhm6B7xJjLVIQqkjiab2M4aKjU= github.com/hashicorp/consul/sdk v0.15.0 h1:2qK9nDrr4tiJKRoxPGhm6B7xJjLVIQqkjiab2M4aKjU=
github.com/hashicorp/consul/sdk v0.15.0/go.mod h1:r/OmRRPbHOe0yxNahLw7G9x5WG17E1BIECMtCjcPSNo= github.com/hashicorp/consul/sdk v0.15.0/go.mod h1:r/OmRRPbHOe0yxNahLw7G9x5WG17E1BIECMtCjcPSNo=
github.com/hashicorp/cronexpr v1.1.1 h1:NJZDd87hGXjoZBdvyCF9mX4DCq5Wy7+A/w+A7q0wn6c= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A=
github.com/hashicorp/cronexpr v1.1.1/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@ -590,8 +592,8 @@ github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM= github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM=
github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0=
github.com/hashicorp/nomad/api v0.0.0-20220506174431-b5665129cd1f h1:jSBbBJcPca465gK6XfwdXRQnFCd63e0oJmqllZTsawI= github.com/hashicorp/nomad/api v0.0.0-20231213195942-64e3dca9274b h1:R1UDhkwGltpSPY9bCBBxIMQd+NY9BkN0vFHnJo/8o8w=
github.com/hashicorp/nomad/api v0.0.0-20220506174431-b5665129cd1f/go.mod h1:b/AoT79m3PEpb6tKCFKva/M+q1rKJNUk5mdu1S8DymM= github.com/hashicorp/nomad/api v0.0.0-20231213195942-64e3dca9274b/go.mod h1:ijDwa6o1uG1jFSq6kERiX2PamKGpZzTmo0XOFNeFZgw=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
@ -1004,8 +1006,9 @@ github.com/shirou/gopsutil/v3 v3.23.11 h1:i3jP9NjCPUz7FiZKxlMnODZkdSIp2gnzfrvsu9
github.com/shirou/gopsutil/v3 v3.23.11/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shirou/gopsutil/v3 v3.23.11/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/shoenig/test v1.7.0 h1:eWcHtTXa6QLnBvm0jgEabMRN/uJ4DMV3M8xUGgRkZmk=
github.com/shoenig/test v1.7.0/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsBHFoI=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=

View file

@ -160,6 +160,12 @@ spec:
can be accessed by client-side APIs, such as can be accessed by client-side APIs, such as
JavaScript. JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds
until the cookie expires. When set to a negative
number, the cookie expires immediately. When
set to zero, the cookie never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
@ -750,6 +756,13 @@ spec:
items: items:
type: string type: string
type: array type: array
includedContentTypes:
description: IncludedContentTypes defines the list of content
types to compare the Content-Type header of the responses before
compressing.
items:
type: string
type: array
minResponseBodyBytes: minResponseBodyBytes:
description: 'MinResponseBodyBytes defines the minimum amount description: 'MinResponseBodyBytes defines the minimum amount
of bytes a response body must have to be compressed. Default: of bytes a response body must have to be compressed. Default:
@ -870,6 +883,12 @@ spec:
description: HTTPOnly defines whether the cookie can description: HTTPOnly defines whether the cookie can
be accessed by client-side APIs, such as JavaScript. be accessed by client-side APIs, such as JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds
until the cookie expires. When set to a negative
number, the cookie expires immediately. When set
to zero, the cookie never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
@ -912,6 +931,12 @@ spec:
This middleware delegates the request authentication to a Service. This middleware delegates the request authentication to a Service.
More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/forwardauth/' More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/forwardauth/'
properties: properties:
addAuthCookiesToResponse:
description: AddAuthCookiesToResponse defines the list of cookies
to copy from the authentication server response to the response.
items:
type: string
type: array
address: address:
description: Address defines the authentication server address. description: Address defines the authentication server address.
type: string type: string
@ -2145,6 +2170,12 @@ spec:
description: HTTPOnly defines whether the cookie description: HTTPOnly defines whether the cookie
can be accessed by client-side APIs, such as JavaScript. can be accessed by client-side APIs, such as JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds
until the cookie expires. When set to a negative
number, the cookie expires immediately. When set
to zero, the cookie never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
@ -2236,6 +2267,12 @@ spec:
description: HTTPOnly defines whether the cookie can be description: HTTPOnly defines whether the cookie can be
accessed by client-side APIs, such as JavaScript. accessed by client-side APIs, such as JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds until
the cookie expires. When set to a negative number, the
cookie expires immediately. When set to zero, the cookie
never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
@ -2343,6 +2380,12 @@ spec:
description: HTTPOnly defines whether the cookie description: HTTPOnly defines whether the cookie
can be accessed by client-side APIs, such as JavaScript. can be accessed by client-side APIs, such as JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds
until the cookie expires. When set to a negative
number, the cookie expires immediately. When set
to zero, the cookie never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
@ -2382,6 +2425,12 @@ spec:
description: HTTPOnly defines whether the cookie can be description: HTTPOnly defines whether the cookie can be
accessed by client-side APIs, such as JavaScript. accessed by client-side APIs, such as JavaScript.
type: boolean type: boolean
maxAge:
description: MaxAge indicates the number of seconds until
the cookie expires. When set to a negative number, the
cookie expires immediately. When set to zero, the cookie
never expires.
type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string

View file

@ -15,6 +15,7 @@ import (
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"regexp" "regexp"
"runtime"
"slices" "slices"
"strings" "strings"
"testing" "testing"
@ -56,8 +57,6 @@ type composeDeploy struct {
Replicas int `yaml:"replicas"` Replicas int `yaml:"replicas"`
} }
var traefikBinary = "../dist/traefik"
type BaseSuite struct { type BaseSuite struct {
suite.Suite suite.Suite
containers map[string]testcontainers.Container containers map[string]testcontainers.Container
@ -308,7 +307,13 @@ func (s *BaseSuite) composeDown() {
} }
func (s *BaseSuite) cmdTraefik(args ...string) (*exec.Cmd, *bytes.Buffer) { func (s *BaseSuite) cmdTraefik(args ...string) (*exec.Cmd, *bytes.Buffer) {
cmd := exec.Command(traefikBinary, args...) binName := "traefik"
if runtime.GOOS == "windows" {
binName += ".exe"
}
traefikBinPath := filepath.Join("..", "dist", runtime.GOOS, runtime.GOARCH, binName)
cmd := exec.Command(traefikBinPath, args...)
s.T().Cleanup(func() { s.T().Cleanup(func() {
s.killCmd(cmd) s.killCmd(cmd)

View file

@ -1,10 +1,13 @@
package main package main
import ( import (
"bytes"
"fmt" "fmt"
"io" "io"
"os" "os"
"path" "path"
"path/filepath"
"reflect"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
@ -16,9 +19,65 @@ import (
"github.com/traefik/paerser/generator" "github.com/traefik/paerser/generator"
"github.com/traefik/paerser/parser" "github.com/traefik/paerser/parser"
"github.com/traefik/traefik/v3/cmd" "github.com/traefik/traefik/v3/cmd"
"github.com/traefik/traefik/v3/pkg/collector/hydratation"
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/config/static"
"gopkg.in/yaml.v3"
) )
var commentGenerated = `## CODE GENERATED AUTOMATICALLY
## THIS FILE MUST NOT BE EDITED BY HAND
`
func main() { func main() {
logger := log.With().Logger()
dynConf := &dynamic.Configuration{}
err := hydratation.Hydrate(dynConf)
if err != nil {
logger.Fatal().Err(err).Send()
}
dynConf.HTTP.Models = map[string]*dynamic.Model{}
clean(dynConf.HTTP.Middlewares)
clean(dynConf.TCP.Middlewares)
clean(dynConf.HTTP.Services)
clean(dynConf.TCP.Services)
clean(dynConf.UDP.Services)
err = tomlWrite("./docs/content/reference/dynamic-configuration/file.toml", dynConf)
if err != nil {
logger.Fatal().Err(err).Send()
}
err = yamlWrite("./docs/content/reference/dynamic-configuration/file.yaml", dynConf)
if err != nil {
logger.Fatal().Err(err).Send()
}
err = labelsWrite("./docs/content/reference/dynamic-configuration", dynConf)
if err != nil {
logger.Fatal().Err(err).Send()
}
staticConf := &static.Configuration{}
err = hydratation.Hydrate(staticConf)
if err != nil {
logger.Fatal().Err(err).Send()
}
delete(staticConf.EntryPoints, "EntryPoint1")
err = tomlWrite("./docs/content/reference/static-configuration/file.toml", staticConf)
if err != nil {
logger.Fatal().Err(err).Send()
}
err = yamlWrite("./docs/content/reference/static-configuration/file.yaml", staticConf)
if err != nil {
logger.Fatal().Err(err).Send()
}
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 interface{}) ([]parser.Flat, error) {
return env.Encode(env.DefaultNamePrefix, i) return env.Encode(env.DefaultNamePrefix, i)
}) })
@ -26,6 +85,144 @@ func main() {
genKVDynConfDoc("./docs/content/reference/dynamic-configuration/kv-ref.md") genKVDynConfDoc("./docs/content/reference/dynamic-configuration/kv-ref.md")
} }
func labelsWrite(outputDir string, element *dynamic.Configuration) error {
cleanServers(element)
etnOpts := parser.EncoderToNodeOpts{OmitEmpty: true, TagName: parser.TagLabel, AllowSliceAsStruct: true}
node, err := parser.EncodeToNode(element, parser.DefaultRootName, etnOpts)
if err != nil {
return err
}
metaOpts := parser.MetadataOpts{TagName: parser.TagLabel, AllowSliceAsStruct: true}
err = parser.AddMetadata(element, node, metaOpts)
if err != nil {
return err
}
labels := make(map[string]string)
encodeNode(labels, node.Name, node)
var keys []string
for k := range labels {
keys = append(keys, k)
}
sort.Strings(keys)
dockerLabels, err := os.Create(filepath.Join(outputDir, "docker-labels.yml"))
if err != nil {
return err
}
defer dockerLabels.Close()
// Write the comment at the beginning of the file
if _, err := dockerLabels.WriteString(commentGenerated); err != nil {
return err
}
for _, k := range keys {
v := labels[k]
if v != "" {
if v == "42000000000" {
v = "42s"
}
fmt.Fprintln(dockerLabels, `- "`+strings.ToLower(k)+`=`+v+`"`)
}
}
return nil
}
func cleanServers(element *dynamic.Configuration) {
for _, svc := range element.HTTP.Services {
if svc.LoadBalancer != nil {
server := svc.LoadBalancer.Servers[0]
svc.LoadBalancer.Servers = nil
svc.LoadBalancer.Servers = append(svc.LoadBalancer.Servers, server)
}
}
for _, svc := range element.TCP.Services {
if svc.LoadBalancer != nil {
server := svc.LoadBalancer.Servers[0]
svc.LoadBalancer.Servers = nil
svc.LoadBalancer.Servers = append(svc.LoadBalancer.Servers, server)
}
}
for _, svc := range element.UDP.Services {
if svc.LoadBalancer != nil {
server := svc.LoadBalancer.Servers[0]
svc.LoadBalancer.Servers = nil
svc.LoadBalancer.Servers = append(svc.LoadBalancer.Servers, server)
}
}
}
func yamlWrite(outputFile string, element any) error {
file, err := os.OpenFile(outputFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o666)
if err != nil {
return err
}
defer file.Close()
// Write the comment at the beginning of the file
if _, err := file.WriteString(commentGenerated); err != nil {
return err
}
buf := new(bytes.Buffer)
encoder := yaml.NewEncoder(buf)
encoder.SetIndent(2)
err = encoder.Encode(element)
if err != nil {
return err
}
_, err = file.Write(buf.Bytes())
return err
}
func tomlWrite(outputFile string, element any) error {
file, err := os.OpenFile(outputFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o666)
if err != nil {
return err
}
defer file.Close()
// Write the comment at the beginning of the file
if _, err := file.WriteString(commentGenerated); err != nil {
return err
}
return toml.NewEncoder(file).Encode(element)
}
func clean(element any) {
valSvcs := reflect.ValueOf(element)
key := valSvcs.MapKeys()[0]
valueSvcRoot := valSvcs.MapIndex(key).Elem()
var svcFieldNames []string
for i := 0; i < valueSvcRoot.NumField(); i++ {
svcFieldNames = append(svcFieldNames, valueSvcRoot.Type().Field(i).Name)
}
sort.Strings(svcFieldNames)
for i, fieldName := range svcFieldNames {
v := reflect.New(valueSvcRoot.Type())
v.Elem().FieldByName(fieldName).Set(valueSvcRoot.FieldByName(fieldName))
valSvcs.SetMapIndex(reflect.ValueOf(fmt.Sprintf("%s%.2d", valueSvcRoot.Type().Name(), i+1)), v)
}
valSvcs.SetMapIndex(reflect.ValueOf(fmt.Sprintf("%s0", valueSvcRoot.Type().Name())), reflect.Value{})
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(interface{}) ([]parser.Flat, error)) {
logger := log.With().Str("file", outputFile).Logger() logger := log.With().Str("file", outputFile).Logger()
@ -117,6 +314,7 @@ func genKVDynConfDoc(outputFile string) {
} }
store := storeWriter{data: map[string]string{}} store := storeWriter{data: map[string]string{}}
c := client{store: store} c := client{store: store}
err = c.load("traefik", conf) err = c.load("traefik", conf)
if err != nil { if err != nil {
@ -130,6 +328,12 @@ func genKVDynConfDoc(outputFile string) {
sort.Strings(keys) sort.Strings(keys)
_, _ = fmt.Fprintf(file, `<!--
CODE GENERATED AUTOMATICALLY
THIS FILE MUST NOT BE EDITED BY HAND
-->
`)
for _, k := range keys { for _, k := range keys {
_, _ = fmt.Fprintf(file, "| `%s` | `%s` |\n", k, store.data[k]) _, _ = fmt.Fprintf(file, "| `%s` | `%s` |\n", k, store.data[k])
} }

66
internal/parser.go Normal file
View file

@ -0,0 +1,66 @@
package main
import (
"fmt"
"reflect"
"strings"
"github.com/traefik/paerser/parser"
)
func encodeNode(labels map[string]string, root string, node *parser.Node) {
for _, child := range node.Children {
if child.Disabled {
continue
}
var sep string
if child.Name[0] != '[' {
sep = "."
}
childName := root + sep + child.Name
if child.RawValue != nil {
encodeRawValue(labels, childName, child.RawValue)
continue
}
if strings.Contains(child.Tag.Get(parser.TagLabel), parser.TagLabelAllowEmpty) {
labels[childName] = "true"
}
if len(child.Children) > 0 {
encodeNode(labels, childName, child)
} else if len(child.Name) > 0 {
labels[childName] = child.Value
}
}
}
func encodeRawValue(labels map[string]string, root string, rawValue interface{}) {
if rawValue == nil {
return
}
tValue := reflect.TypeOf(rawValue)
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{})
for k, v := range r {
switch tv := v.(type) {
case string:
labels[root+"."+k] = tv
case []interface{}:
for i, e := range tv {
encodeRawValue(labels, fmt.Sprintf("%s.%s[%d]", root, k, i), e)
}
default:
encodeRawValue(labels, root+"."+k, v)
}
}
}
}

View file

@ -5,13 +5,14 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/traefik/traefik/v3/pkg/collector/hydratation"
"github.com/traefik/traefik/v3/pkg/config/static" "github.com/traefik/traefik/v3/pkg/config/static"
) )
func Test_createBody(t *testing.T) { func Test_createBody(t *testing.T) {
var staticConfiguration static.Configuration var staticConfiguration static.Configuration
err := hydrate(&staticConfiguration) err := hydratation.Hydrate(&staticConfiguration)
require.NoError(t, err) require.NoError(t, err)
buffer, err := createBody(&staticConfiguration) buffer, err := createBody(&staticConfiguration)

View file

@ -1,4 +1,4 @@
package collector package hydratation
import ( import (
"fmt" "fmt"
@ -17,7 +17,8 @@ const (
defaultMapKeyPrefix = "name" defaultMapKeyPrefix = "name"
) )
func hydrate(element interface{}) error { // Hydrate hydrates a configuration.
func Hydrate(element interface{}) error {
field := reflect.ValueOf(element) field := reflect.ValueOf(element)
return fill(field) return fill(field)
} }
@ -41,9 +42,7 @@ func fill(field reflect.Value) error {
return err return err
} }
case reflect.Interface: case reflect.Interface:
if err := fill(field.Elem()); err != nil { setTyped(field, defaultString)
return err
}
case reflect.String: case reflect.String:
setTyped(field, defaultString) setTyped(field, defaultString)
case reflect.Int: case reflect.Int:
@ -118,7 +117,7 @@ func makeKeyName(typ reflect.Type) string {
case reflect.String, case reflect.String,
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Bool, reflect.Float32, reflect.Float64: reflect.Bool, reflect.Float32, reflect.Float64, reflect.Interface:
return defaultMapKeyPrefix return defaultMapKeyPrefix
default: default:
return typ.Name() return typ.Name()

View file

@ -24,7 +24,7 @@ type Configuration struct {
HTTP *HTTPConfiguration `json:"http,omitempty" toml:"http,omitempty" yaml:"http,omitempty" export:"true"` HTTP *HTTPConfiguration `json:"http,omitempty" toml:"http,omitempty" yaml:"http,omitempty" export:"true"`
TCP *TCPConfiguration `json:"tcp,omitempty" toml:"tcp,omitempty" yaml:"tcp,omitempty" export:"true"` TCP *TCPConfiguration `json:"tcp,omitempty" toml:"tcp,omitempty" yaml:"tcp,omitempty" export:"true"`
UDP *UDPConfiguration `json:"udp,omitempty" toml:"udp,omitempty" yaml:"udp,omitempty" export:"true"` UDP *UDPConfiguration `json:"udp,omitempty" toml:"udp,omitempty" yaml:"udp,omitempty" export:"true"`
TLS *TLSConfiguration `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"` TLS *TLSConfiguration `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"-" export:"true"`
} }
// +k8s:deepcopy-gen=true // +k8s:deepcopy-gen=true

View file

@ -155,6 +155,10 @@ type Cookie struct {
// SameSite defines the same site policy. // SameSite defines the same site policy.
// More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite // More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
SameSite string `json:"sameSite,omitempty" toml:"sameSite,omitempty" yaml:"sameSite,omitempty" export:"true"` SameSite string `json:"sameSite,omitempty" toml:"sameSite,omitempty" yaml:"sameSite,omitempty" export:"true"`
// MaxAge indicates the number of seconds until the cookie expires.
// When set to a negative number, the cookie expires immediately.
// When set to zero, the cookie never expires.
MaxAge int `json:"maxAge,omitempty" toml:"maxAge,omitempty" yaml:"maxAge,omitempty" export:"true"`
} }
// +k8s:deepcopy-gen=true // +k8s:deepcopy-gen=true

View file

@ -159,6 +159,8 @@ type Compress struct {
// ExcludedContentTypes defines the list of content types to compare the Content-Type header of the incoming requests and responses before compressing. // ExcludedContentTypes defines the list of content types to compare the Content-Type header of the incoming requests and responses before compressing.
// `application/grpc` is always excluded. // `application/grpc` is always excluded.
ExcludedContentTypes []string `json:"excludedContentTypes,omitempty" toml:"excludedContentTypes,omitempty" yaml:"excludedContentTypes,omitempty" export:"true"` ExcludedContentTypes []string `json:"excludedContentTypes,omitempty" toml:"excludedContentTypes,omitempty" yaml:"excludedContentTypes,omitempty" export:"true"`
// IncludedContentTypes defines the list of content types to compare the Content-Type header of the responses before compressing.
IncludedContentTypes []string `json:"includedContentTypes,omitempty" toml:"includedContentTypes,omitempty" yaml:"includedContentTypes,omitempty" export:"true"`
// MinResponseBodyBytes defines the minimum amount of bytes a response body must have to be compressed. // MinResponseBodyBytes defines the minimum amount of bytes a response body must have to be compressed.
// Default: 1024. // Default: 1024.
MinResponseBodyBytes int `json:"minResponseBodyBytes,omitempty" toml:"minResponseBodyBytes,omitempty" yaml:"minResponseBodyBytes,omitempty" export:"true"` MinResponseBodyBytes int `json:"minResponseBodyBytes,omitempty" toml:"minResponseBodyBytes,omitempty" yaml:"minResponseBodyBytes,omitempty" export:"true"`
@ -223,6 +225,8 @@ type ForwardAuth struct {
// AuthRequestHeaders defines the list of the headers to copy from the request to the authentication server. // AuthRequestHeaders defines the list of the headers to copy from the request to the authentication server.
// If not set or empty then all request headers are passed. // If not set or empty then all request headers are passed.
AuthRequestHeaders []string `json:"authRequestHeaders,omitempty" toml:"authRequestHeaders,omitempty" yaml:"authRequestHeaders,omitempty" export:"true"` AuthRequestHeaders []string `json:"authRequestHeaders,omitempty" toml:"authRequestHeaders,omitempty" yaml:"authRequestHeaders,omitempty" export:"true"`
// AddAuthCookiesToResponse defines the list of cookies to copy from the authentication server response to the response.
AddAuthCookiesToResponse []string `json:"addAuthCookiesToResponse,omitempty" toml:"addAuthCookiesToResponse,omitempty" yaml:"addAuthCookiesToResponse,omitempty" export:"true"`
} }
// +k8s:deepcopy-gen=true // +k8s:deepcopy-gen=true

View file

@ -132,6 +132,11 @@ func (in *Compress) DeepCopyInto(out *Compress) {
*out = make([]string, len(*in)) *out = make([]string, len(*in))
copy(*out, *in) copy(*out, *in)
} }
if in.IncludedContentTypes != nil {
in, out := &in.IncludedContentTypes, &out.IncludedContentTypes
*out = make([]string, len(*in))
copy(*out, *in)
}
return return
} }
@ -324,6 +329,11 @@ func (in *ForwardAuth) DeepCopyInto(out *ForwardAuth) {
*out = make([]string, len(*in)) *out = make([]string, len(*in))
copy(*out, *in) copy(*out, *in)
} }
if in.AddAuthCookiesToResponse != nil {
in, out := &in.AddAuthCookiesToResponse, &out.AddAuthCookiesToResponse
*out = make([]string, len(*in))
copy(*out, *in)
}
return return
} }

View file

@ -1334,6 +1334,7 @@ func TestEncodeConfiguration(t *testing.T) {
"traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.Name": "foobar", "traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.Name": "foobar",
"traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.HTTPOnly": "true", "traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.HTTPOnly": "true",
"traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.Secure": "false", "traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.Secure": "false",
"traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.MaxAge": "0",
"traefik.HTTP.Services.Service0.LoadBalancer.ServersTransport": "foobar", "traefik.HTTP.Services.Service0.LoadBalancer.ServersTransport": "foobar",
"traefik.HTTP.Services.Service1.LoadBalancer.HealthCheck.Headers.name0": "foobar", "traefik.HTTP.Services.Service1.LoadBalancer.HealthCheck.Headers.name0": "foobar",
"traefik.HTTP.Services.Service1.LoadBalancer.HealthCheck.Headers.name1": "foobar", "traefik.HTTP.Services.Service1.LoadBalancer.HealthCheck.Headers.name1": "foobar",

View file

@ -48,12 +48,18 @@ type forwardAuth struct {
client http.Client client http.Client
trustForwardHeader bool trustForwardHeader bool
authRequestHeaders []string authRequestHeaders []string
addAuthCookiesToResponse map[string]struct{}
} }
// NewForward creates a forward auth middleware. // NewForward creates a forward auth middleware.
func NewForward(ctx context.Context, next http.Handler, config dynamic.ForwardAuth, name string) (http.Handler, error) { func NewForward(ctx context.Context, next http.Handler, config dynamic.ForwardAuth, name string) (http.Handler, error) {
middlewares.GetLogger(ctx, name, typeNameForward).Debug().Msg("Creating middleware") middlewares.GetLogger(ctx, name, typeNameForward).Debug().Msg("Creating middleware")
addAuthCookiesToResponse := make(map[string]struct{})
for _, cookieName := range config.AddAuthCookiesToResponse {
addAuthCookiesToResponse[cookieName] = struct{}{}
}
fa := &forwardAuth{ fa := &forwardAuth{
address: config.Address, address: config.Address,
authResponseHeaders: config.AuthResponseHeaders, authResponseHeaders: config.AuthResponseHeaders,
@ -61,6 +67,7 @@ func NewForward(ctx context.Context, next http.Handler, config dynamic.ForwardAu
name: name, name: name,
trustForwardHeader: config.TrustForwardHeader, trustForwardHeader: config.TrustForwardHeader,
authRequestHeaders: config.AuthRequestHeaders, authRequestHeaders: config.AuthRequestHeaders,
addAuthCookiesToResponse: addAuthCookiesToResponse,
} }
// Ensure our request client does not follow redirects // Ensure our request client does not follow redirects
@ -211,7 +218,35 @@ func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
tracing.LogResponseCode(forwardSpan, forwardResponse.StatusCode, trace.SpanKindClient) tracing.LogResponseCode(forwardSpan, forwardResponse.StatusCode, trace.SpanKindClient)
req.RequestURI = req.URL.RequestURI() req.RequestURI = req.URL.RequestURI()
authCookies := forwardResponse.Cookies()
if len(authCookies) == 0 {
fa.next.ServeHTTP(rw, req) fa.next.ServeHTTP(rw, req)
return
}
fa.next.ServeHTTP(middlewares.NewResponseModifier(rw, req, fa.buildModifier(authCookies)), req)
}
func (fa *forwardAuth) buildModifier(authCookies []*http.Cookie) func(res *http.Response) error {
return func(res *http.Response) error {
cookies := res.Cookies()
res.Header.Del("Set-Cookie")
for _, cookie := range cookies {
if _, found := fa.addAuthCookiesToResponse[cookie.Name]; !found {
res.Header.Add("Set-Cookie", cookie.String())
}
}
for _, cookie := range authCookies {
if _, found := fa.addAuthCookiesToResponse[cookie.Name]; found {
res.Header.Add("Set-Cookie", cookie.String())
}
}
return nil
}
} }
func writeHeader(req, forwardReq *http.Request, trustForwardHeader bool, allowedHeaders []string) { func writeHeader(req, forwardReq *http.Request, trustForwardHeader bool, allowedHeaders []string) {

View file

@ -66,6 +66,8 @@ func TestForwardAuthSuccess(t *testing.T) {
w.Header().Add("X-Auth-Group", "group1") w.Header().Add("X-Auth-Group", "group1")
w.Header().Add("X-Auth-Group", "group2") w.Header().Add("X-Auth-Group", "group2")
w.Header().Add("Foo-Bar", "auth-value") w.Header().Add("Foo-Bar", "auth-value")
w.Header().Add("Set-Cookie", "authCookie=Auth")
w.Header().Add("Set-Cookie", "authCookieNotAdded=Auth")
fmt.Fprintln(w, "Success") fmt.Fprintln(w, "Success")
})) }))
t.Cleanup(server.Close) t.Cleanup(server.Close)
@ -76,6 +78,9 @@ func TestForwardAuthSuccess(t *testing.T) {
assert.Equal(t, []string{"group1", "group2"}, r.Header["X-Auth-Group"]) assert.Equal(t, []string{"group1", "group2"}, r.Header["X-Auth-Group"])
assert.Equal(t, "auth-value", r.Header.Get("Foo-Bar")) assert.Equal(t, "auth-value", r.Header.Get("Foo-Bar"))
assert.Empty(t, r.Header.Get("Foo-Baz")) assert.Empty(t, r.Header.Get("Foo-Baz"))
w.Header().Add("Set-Cookie", "authCookie=Backend")
w.Header().Add("Set-Cookie", "backendCookie=Backend")
w.Header().Add("Other-Header", "BackendHeaderValue")
fmt.Fprintln(w, "traefik") fmt.Fprintln(w, "traefik")
}) })
@ -83,6 +88,7 @@ func TestForwardAuthSuccess(t *testing.T) {
Address: server.URL, Address: server.URL,
AuthResponseHeaders: []string{"X-Auth-User", "X-Auth-Group"}, AuthResponseHeaders: []string{"X-Auth-User", "X-Auth-Group"},
AuthResponseHeadersRegex: "^Foo-", AuthResponseHeadersRegex: "^Foo-",
AddAuthCookiesToResponse: []string{"authCookie"},
} }
middleware, err := NewForward(context.Background(), next, auth, "authTest") middleware, err := NewForward(context.Background(), next, auth, "authTest")
require.NoError(t, err) require.NoError(t, err)
@ -97,6 +103,8 @@ func TestForwardAuthSuccess(t *testing.T) {
res, err := http.DefaultClient.Do(req) res, err := http.DefaultClient.Do(req)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, http.StatusOK, res.StatusCode) assert.Equal(t, http.StatusOK, res.StatusCode)
assert.Equal(t, []string{"backendCookie=Backend", "authCookie=Auth"}, res.Header["Set-Cookie"])
assert.Equal(t, []string{"BackendHeaderValue"}, res.Header["Other-Header"])
body, err := io.ReadAll(res.Body) body, err := io.ReadAll(res.Body)
require.NoError(t, err) require.NoError(t, err)

View file

@ -22,7 +22,11 @@ const (
// Config is the Brotli handler configuration. // Config is the Brotli handler configuration.
type Config struct { type Config struct {
// ExcludedContentTypes is the list of content types for which we should not compress. // ExcludedContentTypes is the list of content types for which we should not compress.
// Mutually exclusive with the IncludedContentTypes option.
ExcludedContentTypes []string ExcludedContentTypes []string
// IncludedContentTypes is the list of content types for which compression should be exclusively enabled.
// Mutually exclusive with the ExcludedContentTypes option.
IncludedContentTypes []string
// MinSize is the minimum size (in bytes) required to enable compression. // MinSize is the minimum size (in bytes) required to enable compression.
MinSize int MinSize int
} }
@ -33,14 +37,28 @@ func NewWrapper(cfg Config) (func(http.Handler) http.HandlerFunc, error) {
return nil, fmt.Errorf("minimum size must be greater than or equal to zero") return nil, fmt.Errorf("minimum size must be greater than or equal to zero")
} }
var contentTypes []parsedContentType if len(cfg.ExcludedContentTypes) > 0 && len(cfg.IncludedContentTypes) > 0 {
return nil, fmt.Errorf("excludedContentTypes and includedContentTypes options are mutually exclusive")
}
var excludedContentTypes []parsedContentType
for _, v := range cfg.ExcludedContentTypes { for _, v := range cfg.ExcludedContentTypes {
mediaType, params, err := mime.ParseMediaType(v) mediaType, params, err := mime.ParseMediaType(v)
if err != nil { if err != nil {
return nil, fmt.Errorf("parsing media type: %w", err) return nil, fmt.Errorf("parsing excluded media type: %w", err)
} }
contentTypes = append(contentTypes, parsedContentType{mediaType, params}) excludedContentTypes = append(excludedContentTypes, parsedContentType{mediaType, params})
}
var includedContentTypes []parsedContentType
for _, v := range cfg.IncludedContentTypes {
mediaType, params, err := mime.ParseMediaType(v)
if err != nil {
return nil, fmt.Errorf("parsing included media type: %w", err)
}
includedContentTypes = append(includedContentTypes, parsedContentType{mediaType, params})
} }
return func(h http.Handler) http.HandlerFunc { return func(h http.Handler) http.HandlerFunc {
@ -52,7 +70,8 @@ func NewWrapper(cfg Config) (func(http.Handler) http.HandlerFunc, error) {
bw: brotli.NewWriter(rw), bw: brotli.NewWriter(rw),
minSize: cfg.MinSize, minSize: cfg.MinSize,
statusCode: http.StatusOK, statusCode: http.StatusOK,
excludedContentTypes: contentTypes, excludedContentTypes: excludedContentTypes,
includedContentTypes: includedContentTypes,
} }
defer brw.close() defer brw.close()
@ -69,6 +88,7 @@ type responseWriter struct {
minSize int minSize int
excludedContentTypes []parsedContentType excludedContentTypes []parsedContentType
includedContentTypes []parsedContentType
buf []byte buf []byte
hijacked bool hijacked bool
@ -121,11 +141,25 @@ func (r *responseWriter) Write(p []byte) (int, error) {
return r.rw.Write(p) return r.rw.Write(p)
} }
// Disable compression according to user wishes in excludedContentTypes. // Disable compression according to user wishes in excludedContentTypes or includedContentTypes.
if ct := r.rw.Header().Get(contentType); ct != "" { if ct := r.rw.Header().Get(contentType); ct != "" {
mediaType, params, err := mime.ParseMediaType(ct) mediaType, params, err := mime.ParseMediaType(ct)
if err != nil { if err != nil {
return 0, fmt.Errorf("parsing media type: %w", err) return 0, fmt.Errorf("parsing content-type media type: %w", err)
}
if len(r.includedContentTypes) > 0 {
var found bool
for _, includedContentType := range r.includedContentTypes {
if includedContentType.equals(mediaType, params) {
found = true
break
}
}
if !found {
r.compressionDisabled = true
return r.rw.Write(p)
}
} }
for _, excludedContentType := range r.excludedContentTypes { for _, excludedContentType := range r.excludedContentTypes {

View file

@ -293,7 +293,6 @@ func Test_ExcludedContentTypes(t *testing.T) {
{ {
desc: "Always compress when content types are empty", desc: "Always compress when content types are empty",
contentType: "", contentType: "",
excludedContentTypes: []string{},
expCompression: true, expCompression: true,
}, },
{ {
@ -389,6 +388,111 @@ func Test_ExcludedContentTypes(t *testing.T) {
} }
} }
func Test_IncludedContentTypes(t *testing.T) {
testCases := []struct {
desc string
contentType string
includedContentTypes []string
expCompression bool
}{
{
desc: "Always compress when content types are empty",
contentType: "",
expCompression: true,
},
{
desc: "MIME match",
contentType: "application/json",
includedContentTypes: []string{"application/json"},
expCompression: true,
},
{
desc: "MIME no match",
contentType: "text/xml",
includedContentTypes: []string{"application/json"},
expCompression: false,
},
{
desc: "MIME match with no other directive ignores non-MIME directives",
contentType: "application/json; charset=utf-8",
includedContentTypes: []string{"application/json"},
expCompression: true,
},
{
desc: "MIME match with other directives requires all directives be equal, different charset",
contentType: "application/json; charset=ascii",
includedContentTypes: []string{"application/json; charset=utf-8"},
expCompression: false,
},
{
desc: "MIME match with other directives requires all directives be equal, same charset",
contentType: "application/json; charset=utf-8",
includedContentTypes: []string{"application/json; charset=utf-8"},
expCompression: true,
},
{
desc: "MIME match with other directives requires all directives be equal, missing charset",
contentType: "application/json",
includedContentTypes: []string{"application/json; charset=ascii"},
expCompression: false,
},
{
desc: "MIME match case insensitive",
contentType: "Application/Json",
includedContentTypes: []string{"application/json"},
expCompression: true,
},
{
desc: "MIME match ignore whitespace",
contentType: "application/json;charset=utf-8",
includedContentTypes: []string{"application/json; charset=utf-8"},
expCompression: true,
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
cfg := Config{
MinSize: 1024,
IncludedContentTypes: test.includedContentTypes,
}
h := mustNewWrapper(t, cfg)(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.Header().Set(contentType, test.contentType)
rw.WriteHeader(http.StatusOK)
_, err := rw.Write(bigTestBody)
require.NoError(t, err)
}))
req, _ := http.NewRequest(http.MethodGet, "/whatever", nil)
req.Header.Set(acceptEncoding, "br")
rw := httptest.NewRecorder()
h.ServeHTTP(rw, req)
assert.Equal(t, http.StatusOK, rw.Code)
if test.expCompression {
assert.Equal(t, "br", rw.Header().Get(contentEncoding))
got, err := io.ReadAll(brotli.NewReader(rw.Body))
assert.NoError(t, err)
assert.Equal(t, bigTestBody, got)
} else {
assert.NotEqual(t, "br", rw.Header().Get("Content-Encoding"))
got, err := io.ReadAll(rw.Body)
assert.NoError(t, err)
assert.Equal(t, bigTestBody, got)
}
})
}
}
func Test_FlushExcludedContentTypes(t *testing.T) { func Test_FlushExcludedContentTypes(t *testing.T) {
testCases := []struct { testCases := []struct {
desc string desc string
@ -399,7 +503,6 @@ func Test_FlushExcludedContentTypes(t *testing.T) {
{ {
desc: "Always compress when content types are empty", desc: "Always compress when content types are empty",
contentType: "", contentType: "",
excludedContentTypes: []string{},
expCompression: true, expCompression: true,
}, },
{ {
@ -509,6 +612,125 @@ func Test_FlushExcludedContentTypes(t *testing.T) {
} }
} }
func Test_FlushIncludedContentTypes(t *testing.T) {
testCases := []struct {
desc string
contentType string
includedContentTypes []string
expCompression bool
}{
{
desc: "Always compress when content types are empty",
contentType: "",
expCompression: true,
},
{
desc: "MIME match",
contentType: "application/json",
includedContentTypes: []string{"application/json"},
expCompression: true,
},
{
desc: "MIME no match",
contentType: "text/xml",
includedContentTypes: []string{"application/json"},
expCompression: false,
},
{
desc: "MIME match with no other directive ignores non-MIME directives",
contentType: "application/json; charset=utf-8",
includedContentTypes: []string{"application/json"},
expCompression: true,
},
{
desc: "MIME match with other directives requires all directives be equal, different charset",
contentType: "application/json; charset=ascii",
includedContentTypes: []string{"application/json; charset=utf-8"},
expCompression: false,
},
{
desc: "MIME match with other directives requires all directives be equal, same charset",
contentType: "application/json; charset=utf-8",
includedContentTypes: []string{"application/json; charset=utf-8"},
expCompression: true,
},
{
desc: "MIME match with other directives requires all directives be equal, missing charset",
contentType: "application/json",
includedContentTypes: []string{"application/json; charset=ascii"},
expCompression: false,
},
{
desc: "MIME match case insensitive",
contentType: "Application/Json",
includedContentTypes: []string{"application/json"},
expCompression: true,
},
{
desc: "MIME match ignore whitespace",
contentType: "application/json;charset=utf-8",
includedContentTypes: []string{"application/json; charset=utf-8"},
expCompression: true,
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
cfg := Config{
MinSize: 1024,
IncludedContentTypes: test.includedContentTypes,
}
h := mustNewWrapper(t, cfg)(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.Header().Set(contentType, test.contentType)
rw.WriteHeader(http.StatusOK)
tb := bigTestBody
for len(tb) > 0 {
// Write 100 bytes per run
// Detection should not be affected (we send 100 bytes)
toWrite := 100
if toWrite > len(tb) {
toWrite = len(tb)
}
_, err := rw.Write(tb[:toWrite])
require.NoError(t, err)
// Flush between each write
rw.(http.Flusher).Flush()
tb = tb[toWrite:]
}
}))
req, _ := http.NewRequest(http.MethodGet, "/whatever", nil)
req.Header.Set(acceptEncoding, "br")
// This doesn't allow checking flushes, but we validate if content is correct.
rw := httptest.NewRecorder()
h.ServeHTTP(rw, req)
assert.Equal(t, http.StatusOK, rw.Code)
if test.expCompression {
assert.Equal(t, "br", rw.Header().Get(contentEncoding))
got, err := io.ReadAll(brotli.NewReader(rw.Body))
assert.NoError(t, err)
assert.Equal(t, bigTestBody, got)
} else {
assert.NotEqual(t, "br", rw.Header().Get(contentEncoding))
got, err := io.ReadAll(rw.Body)
assert.NoError(t, err)
assert.Equal(t, bigTestBody, got)
}
})
}
}
func mustNewWrapper(t *testing.T, cfg Config) func(http.Handler) http.HandlerFunc { func mustNewWrapper(t *testing.T, cfg Config) func(http.Handler) http.HandlerFunc {
t.Helper() t.Helper()

View file

@ -26,6 +26,7 @@ type compress struct {
next http.Handler next http.Handler
name string name string
excludes []string excludes []string
includes []string
minSize int minSize int
brotliHandler http.Handler brotliHandler http.Handler
@ -36,16 +37,30 @@ type compress struct {
func New(ctx context.Context, next http.Handler, conf dynamic.Compress, name string) (http.Handler, error) { func New(ctx context.Context, next http.Handler, conf dynamic.Compress, name string) (http.Handler, error) {
middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware") middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware")
if len(conf.ExcludedContentTypes) > 0 && len(conf.IncludedContentTypes) > 0 {
return nil, fmt.Errorf("excludedContentTypes and includedContentTypes options are mutually exclusive")
}
excludes := []string{"application/grpc"} excludes := []string{"application/grpc"}
for _, v := range conf.ExcludedContentTypes { for _, v := range conf.ExcludedContentTypes {
mediaType, _, err := mime.ParseMediaType(v) mediaType, _, err := mime.ParseMediaType(v)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("parsing excluded media type: %w", err)
} }
excludes = append(excludes, mediaType) excludes = append(excludes, mediaType)
} }
var includes []string
for _, v := range conf.IncludedContentTypes {
mediaType, _, err := mime.ParseMediaType(v)
if err != nil {
return nil, fmt.Errorf("parsing included media type: %w", err)
}
includes = append(includes, mediaType)
}
minSize := DefaultMinSize minSize := DefaultMinSize
if conf.MinResponseBodyBytes > 0 { if conf.MinResponseBodyBytes > 0 {
minSize = conf.MinResponseBodyBytes minSize = conf.MinResponseBodyBytes
@ -55,6 +70,7 @@ func New(ctx context.Context, next http.Handler, conf dynamic.Compress, name str
next: next, next: next,
name: name, name: name,
excludes: excludes, excludes: excludes,
includes: includes,
minSize: minSize, minSize: minSize,
} }
@ -92,11 +108,11 @@ func (c *compress) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
return return
} }
// Client allows us to do whatever we want, so we br compress. // Client doesn't specify a preferred encoding, for compatibility don't encode the request
// See https://www.rfc-editor.org/rfc/rfc9110.html#section-12.5.3 // See https://github.com/traefik/traefik/issues/9734
acceptEncoding, ok := req.Header["Accept-Encoding"] acceptEncoding, ok := req.Header["Accept-Encoding"]
if !ok { if !ok {
c.brotliHandler.ServeHTTP(rw, req) c.next.ServeHTTP(rw, req)
return return
} }
@ -118,10 +134,21 @@ func (c *compress) GetTracingInformation() (string, string, trace.SpanKind) {
} }
func (c *compress) newGzipHandler() (http.Handler, error) { func (c *compress) newGzipHandler() (http.Handler, error) {
wrapper, err := gzhttp.NewWrapper( var wrapper func(http.Handler) http.HandlerFunc
var err error
if len(c.includes) > 0 {
wrapper, err = gzhttp.NewWrapper(
gzhttp.ContentTypes(c.includes),
gzhttp.MinSize(c.minSize),
)
} else {
wrapper, err = gzhttp.NewWrapper(
gzhttp.ExceptContentTypes(c.excludes), gzhttp.ExceptContentTypes(c.excludes),
gzhttp.MinSize(c.minSize), gzhttp.MinSize(c.minSize),
) )
}
if err != nil { if err != nil {
return nil, fmt.Errorf("new gzip wrapper: %w", err) return nil, fmt.Errorf("new gzip wrapper: %w", err)
} }
@ -130,9 +157,11 @@ func (c *compress) newGzipHandler() (http.Handler, error) {
} }
func (c *compress) newBrotliHandler() (http.Handler, error) { func (c *compress) newBrotliHandler() (http.Handler, error) {
cfg := brotli.Config{ cfg := brotli.Config{MinSize: c.minSize}
ExcludedContentTypes: c.excludes, if len(c.includes) > 0 {
MinSize: c.minSize, cfg.IncludedContentTypes = c.includes
} else {
cfg.ExcludedContentTypes = c.excludes
} }
wrapper, err := brotli.NewWrapper(cfg) wrapper, err := brotli.NewWrapper(cfg)

View file

@ -10,7 +10,6 @@ import (
"net/textproto" "net/textproto"
"testing" "testing"
"github.com/andybalholm/brotli"
"github.com/klauspost/compress/gzhttp" "github.com/klauspost/compress/gzhttp"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -35,7 +34,7 @@ func TestNegotiation(t *testing.T) {
}{ }{
{ {
desc: "no accept header", desc: "no accept header",
expEncoding: "br", expEncoding: "",
}, },
{ {
desc: "unsupported accept header", desc: "unsupported accept header",
@ -151,7 +150,7 @@ func TestShouldNotCompressWhenContentEncodingHeader(t *testing.T) {
assert.EqualValues(t, rw.Body.Bytes(), fakeCompressedBody) assert.EqualValues(t, rw.Body.Bytes(), fakeCompressedBody)
} }
func TestShouldCompressWhenNoAcceptEncodingHeader(t *testing.T) { func TestShouldNotCompressWhenNoAcceptEncodingHeader(t *testing.T) {
req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil) req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil)
fakeBody := generateBytes(gzhttp.DefaultMinSize) fakeBody := generateBytes(gzhttp.DefaultMinSize)
@ -167,12 +166,9 @@ func TestShouldCompressWhenNoAcceptEncodingHeader(t *testing.T) {
rw := httptest.NewRecorder() rw := httptest.NewRecorder()
handler.ServeHTTP(rw, req) handler.ServeHTTP(rw, req)
assert.Equal(t, brotliValue, rw.Header().Get(contentEncodingHeader)) assert.Empty(t, rw.Header().Get(contentEncodingHeader))
assert.Equal(t, acceptEncodingHeader, rw.Header().Get(varyHeader)) assert.Empty(t, rw.Header().Get(varyHeader))
assert.EqualValues(t, rw.Body.Bytes(), fakeBody)
got, err := io.ReadAll(brotli.NewReader(rw.Body))
require.NoError(t, err)
assert.Equal(t, got, fakeBody)
} }
func TestShouldNotCompressWhenIdentityAcceptEncodingHeader(t *testing.T) { func TestShouldNotCompressWhenIdentityAcceptEncodingHeader(t *testing.T) {
@ -275,7 +271,28 @@ func TestShouldNotCompressWhenSpecificContentType(t *testing.T) {
respContentType: "text/event-stream", respContentType: "text/event-stream",
}, },
{ {
desc: "application/grpc", desc: "Include Response Content-Type",
conf: dynamic.Compress{
IncludedContentTypes: []string{"text/plain"},
},
respContentType: "text/html",
},
{
desc: "Ignoring application/grpc with exclude option",
conf: dynamic.Compress{
ExcludedContentTypes: []string{"application/json"},
},
reqContentType: "application/grpc",
},
{
desc: "Ignoring application/grpc with include option",
conf: dynamic.Compress{
IncludedContentTypes: []string{"application/json"},
},
reqContentType: "application/grpc",
},
{
desc: "Ignoring application/grpc with no option",
conf: dynamic.Compress{}, conf: dynamic.Compress{},
reqContentType: "application/grpc", reqContentType: "application/grpc",
}, },
@ -316,6 +333,52 @@ func TestShouldNotCompressWhenSpecificContentType(t *testing.T) {
} }
} }
func TestShouldCompressWhenSpecificContentType(t *testing.T) {
baseBody := generateBytes(gzhttp.DefaultMinSize)
testCases := []struct {
desc string
conf dynamic.Compress
respContentType string
}{
{
desc: "Include Response Content-Type",
conf: dynamic.Compress{
IncludedContentTypes: []string{"text/html"},
},
respContentType: "text/html",
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil)
req.Header.Add(acceptEncodingHeader, gzipValue)
next := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.Header().Set(contentTypeHeader, test.respContentType)
if _, err := rw.Write(baseBody); err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
}
})
handler, err := New(context.Background(), next, test.conf, "test")
require.NoError(t, err)
rw := httptest.NewRecorder()
handler.ServeHTTP(rw, req)
assert.Equal(t, gzipValue, rw.Header().Get(contentEncodingHeader))
assert.Equal(t, acceptEncodingHeader, rw.Header().Get(varyHeader))
assert.NotEqualValues(t, rw.Body.Bytes(), baseBody)
})
}
}
func TestIntegrationShouldNotCompress(t *testing.T) { func TestIntegrationShouldNotCompress(t *testing.T) {
fakeCompressedBody := generateBytes(100000) fakeCompressedBody := generateBytes(100000)

View file

@ -8,6 +8,7 @@ import (
"strings" "strings"
"github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/middlewares"
"github.com/vulcand/oxy/v2/forward" "github.com/vulcand/oxy/v2/forward"
) )
@ -58,7 +59,7 @@ func (s *Header) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
// If there is a next, call it. // If there is a next, call it.
if s.next != nil { if s.next != nil {
s.next.ServeHTTP(newResponseModifier(rw, req, s.PostRequestModifyResponseHeaders), req) s.next.ServeHTTP(middlewares.NewResponseModifier(rw, req, s.PostRequestModifyResponseHeaders), req)
} }
} }

View file

@ -4,6 +4,7 @@ import (
"net/http" "net/http"
"github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/middlewares"
"github.com/unrolled/secure" "github.com/unrolled/secure"
) )
@ -45,6 +46,6 @@ func newSecure(next http.Handler, cfg dynamic.Headers, contextKey string) *secur
func (s secureHeader) ServeHTTP(rw http.ResponseWriter, req *http.Request) { func (s secureHeader) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
s.secure.HandlerFuncWithNextForRequestOnly(rw, req, func(writer http.ResponseWriter, request *http.Request) { s.secure.HandlerFuncWithNextForRequestOnly(rw, req, func(writer http.ResponseWriter, request *http.Request) {
s.next.ServeHTTP(newResponseModifier(writer, request, s.secure.ModifyResponseHeaders), request) s.next.ServeHTTP(middlewares.NewResponseModifier(writer, request, s.secure.ModifyResponseHeaders), request)
}) })
} }

View file

@ -1,4 +1,4 @@
package headers package middlewares
import ( import (
"bufio" "bufio"
@ -9,7 +9,8 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
type responseModifier struct { // ResponseModifier is a ResponseWriter to modify the response headers before sending them.
type ResponseModifier struct {
req *http.Request req *http.Request
rw http.ResponseWriter rw http.ResponseWriter
@ -21,9 +22,10 @@ type responseModifier struct {
modifierErr error // returned by modifier call modifierErr error // returned by modifier call
} }
// modifier can be nil. // NewResponseModifier returns a new ResponseModifier instance.
func newResponseModifier(w http.ResponseWriter, r *http.Request, modifier func(*http.Response) error) http.ResponseWriter { // The given modifier can be nil.
return &responseModifier{ func NewResponseModifier(w http.ResponseWriter, r *http.Request, modifier func(*http.Response) error) http.ResponseWriter {
return &ResponseModifier{
req: r, req: r,
rw: w, rw: w,
modifier: modifier, modifier: modifier,
@ -33,7 +35,7 @@ func newResponseModifier(w http.ResponseWriter, r *http.Request, modifier func(*
// WriteHeader is, in the specific case of 1xx status codes, a direct call to the wrapped ResponseWriter, without marking headers as sent, // WriteHeader is, in the specific case of 1xx status codes, a direct call to the wrapped ResponseWriter, without marking headers as sent,
// allowing so further calls. // allowing so further calls.
func (r *responseModifier) WriteHeader(code int) { func (r *ResponseModifier) WriteHeader(code int) {
if r.headersSent { if r.headersSent {
return return
} }
@ -73,11 +75,11 @@ func (r *responseModifier) WriteHeader(code int) {
r.rw.WriteHeader(code) r.rw.WriteHeader(code)
} }
func (r *responseModifier) Header() http.Header { func (r *ResponseModifier) Header() http.Header {
return r.rw.Header() return r.rw.Header()
} }
func (r *responseModifier) Write(b []byte) (int, error) { func (r *ResponseModifier) Write(b []byte) (int, error) {
r.WriteHeader(r.code) r.WriteHeader(r.code)
if r.modifierErr != nil { if r.modifierErr != nil {
return 0, r.modifierErr return 0, r.modifierErr
@ -87,7 +89,7 @@ func (r *responseModifier) Write(b []byte) (int, error) {
} }
// Hijack hijacks the connection. // Hijack hijacks the connection.
func (r *responseModifier) Hijack() (net.Conn, *bufio.ReadWriter, error) { func (r *ResponseModifier) Hijack() (net.Conn, *bufio.ReadWriter, error) {
if h, ok := r.rw.(http.Hijacker); ok { if h, ok := r.rw.(http.Hijacker); ok {
return h.Hijack() return h.Hijack()
} }
@ -96,7 +98,7 @@ func (r *responseModifier) Hijack() (net.Conn, *bufio.ReadWriter, error) {
} }
// Flush sends any buffered data to the client. // Flush sends any buffered data to the client.
func (r *responseModifier) Flush() { func (r *ResponseModifier) Flush() {
if flusher, ok := r.rw.(http.Flusher); ok { if flusher, ok := r.rw.(http.Flusher); ok {
flusher.Flush() flusher.Flush()
} }

View file

@ -731,6 +731,7 @@ func createForwardAuthMiddleware(k8sClient Client, namespace string, auth *traef
AuthResponseHeaders: auth.AuthResponseHeaders, AuthResponseHeaders: auth.AuthResponseHeaders,
AuthResponseHeadersRegex: auth.AuthResponseHeadersRegex, AuthResponseHeadersRegex: auth.AuthResponseHeadersRegex,
AuthRequestHeaders: auth.AuthRequestHeaders, AuthRequestHeaders: auth.AuthRequestHeaders,
AddAuthCookiesToResponse: auth.AddAuthCookiesToResponse,
} }
if auth.TLS == nil { if auth.TLS == nil {

View file

@ -157,6 +157,8 @@ type ForwardAuth struct {
AuthRequestHeaders []string `json:"authRequestHeaders,omitempty"` AuthRequestHeaders []string `json:"authRequestHeaders,omitempty"`
// TLS defines the configuration used to secure the connection to the authentication server. // TLS defines the configuration used to secure the connection to the authentication server.
TLS *ClientTLS `json:"tls,omitempty"` TLS *ClientTLS `json:"tls,omitempty"`
// AddAuthCookiesToResponse defines the list of cookies to copy from the authentication server response to the response.
AddAuthCookiesToResponse []string `json:"addAuthCookiesToResponse,omitempty"`
} }
// ClientTLS holds the client TLS configuration. // ClientTLS holds the client TLS configuration.

View file

@ -215,6 +215,11 @@ func (in *ForwardAuth) DeepCopyInto(out *ForwardAuth) {
*out = new(ClientTLS) *out = new(ClientTLS)
**out = **in **out = **in
} }
if in.AddAuthCookiesToResponse != nil {
in, out := &in.AddAuthCookiesToResponse, &out.AddAuthCookiesToResponse
*out = make([]string, len(*in))
copy(*out, *in)
}
return return
} }

View file

@ -25,6 +25,7 @@ type stickyCookie struct {
secure bool secure bool
httpOnly bool httpOnly bool
sameSite string sameSite string
maxAge int
} }
func convertSameSite(sameSite string) http.SameSite { func convertSameSite(sameSite string) http.SameSite {
@ -77,6 +78,7 @@ func New(sticky *dynamic.Sticky, wantHealthCheck bool) *Balancer {
secure: sticky.Cookie.Secure, secure: sticky.Cookie.Secure,
httpOnly: sticky.Cookie.HTTPOnly, httpOnly: sticky.Cookie.HTTPOnly,
sameSite: sticky.Cookie.SameSite, sameSite: sticky.Cookie.SameSite,
maxAge: sticky.Cookie.MaxAge,
} }
} }
@ -238,6 +240,7 @@ func (b *Balancer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
HttpOnly: b.stickyCookie.httpOnly, HttpOnly: b.stickyCookie.httpOnly,
Secure: b.stickyCookie.secure, Secure: b.stickyCookie.secure,
SameSite: convertSameSite(b.stickyCookie.sameSite), SameSite: convertSameSite(b.stickyCookie.sameSite),
MaxAge: b.stickyCookie.maxAge,
} }
http.SetCookie(w, cookie) http.SetCookie(w, cookie)
} }

View file

@ -225,6 +225,7 @@ func TestSticky(t *testing.T) {
Secure: true, Secure: true,
HTTPOnly: true, HTTPOnly: true,
SameSite: "none", SameSite: "none",
MaxAge: 42,
}, },
}, false) }, false)
@ -261,6 +262,7 @@ func TestSticky(t *testing.T) {
assert.True(t, recorder.cookies["test"].HttpOnly) assert.True(t, recorder.cookies["test"].HttpOnly)
assert.True(t, recorder.cookies["test"].Secure) assert.True(t, recorder.cookies["test"].Secure)
assert.Equal(t, http.SameSiteNoneMode, recorder.cookies["test"].SameSite) assert.Equal(t, http.SameSiteNoneMode, recorder.cookies["test"].SameSite)
assert.Equal(t, 42, recorder.cookies["test"].MaxAge)
} }
func TestSticky_FallBack(t *testing.T) { func TestSticky_FallBack(t *testing.T) {

View file

@ -1,30 +0,0 @@
#!/usr/bin/env bash
set -e
rm -f dist/traefik
FLAGS=()
if [ -n "${VERBOSE}" ]; then
FLAGS+=(-v)
fi
if [ -z "${VERSION}" ]; then
VERSION=$(git rev-parse HEAD)
fi
if [ -z "$CODENAME" ]; then
CODENAME=cheddar
fi
if [ -z "$DATE" ]; then
DATE=$(date -u '+%Y-%m-%d_%I:%M:%S%p')
fi
# Build binaries
# shellcheck disable=SC2086
# shellcheck disable=SC2048
CGO_ENABLED=0 GOGC=off 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" \
-installsuffix nocgo -o dist/traefik ./cmd/traefik

View file

@ -1,4 +0,0 @@
#!/usr/bin/env bash
set -e
go generate

View file

@ -1,35 +0,0 @@
#!/usr/bin/env bash
set -e
export GO111MODULE=on
export GOPROXY=https://proxy.golang.org
# List of bundles to create when no argument is passed
DEFAULT_BUNDLES=(
generate
validate-lint
binary
test-unit
test-integration
)
SCRIPT_DIR="$(cd "$(dirname "${0}")" && pwd -P)"
bundle() {
local bundle="$1"; shift
echo "---> Making bundle: $(basename "${bundle}") (in $SCRIPT_DIR)"
# shellcheck source=/dev/null
source "${SCRIPT_DIR}/${bundle}"
}
if [ $# -lt 1 ]; then
bundles=${DEFAULT_BUNDLES[*]}
else
bundles=${*}
fi
# shellcheck disable=SC2048
for bundle in ${bundles[*]}; do
bundle "${bundle}"
echo
done

28
script/release-packages.sh Executable file
View file

@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -e
if [ -n "${SEMAPHORE_GIT_TAG_NAME}" ]; then
echo "Releasing packages..."
else
echo "Skipping release"
exit 0
fi
rm -rf dist
for os in linux darwin windows freebsd openbsd; do
goreleaser release --snapshot --skip=publish -p 2 --timeout="90m" --config "$(go run ./internal/release "$os")"
go clean -cache
done
cat dist/**/*_checksums.txt >> dist/traefik_${VERSION}_checksums.txt
rm dist/**/*_checksums.txt
tar cfz dist/traefik-${VERSION}.src.tar.gz \
--exclude-vcs \
--exclude .idea \
--exclude .travis \
--exclude .semaphoreci \
--exclude .github \
--exclude dist .
chown -R $(id -u):$(id -g) dist/

View file

@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -e
export DEST=.
echo "Testing against..."
docker version
# shellcheck disable=SC2086
# shellcheck disable=SC2048
go test ./integration -test.timeout=20m -failfast -v ${TESTFLAGS[*]}

View file

@ -1,29 +0,0 @@
#!/usr/bin/env bash
set -e
RED=$'\033[31m'
GREEN=$'\033[32m'
TEXTRESET=$'\033[0m' # reset the foreground colour
# -failfast -timeout=5m
TESTFLAGS=(-cover "-coverprofile=cover.out" "${TESTFLAGS}")
if [ -n "${VERBOSE}" ]; then
TESTFLAGS+=(-v)
elif [ -n "${VERBOSE_UNIT}" ]; then
TESTFLAGS+=(-v)
fi
set +e
# shellcheck disable=SC2086
# shellcheck disable=SC2048
go test ${TESTFLAGS[*]} ./pkg/... ./cmd/...
CODE=$?
if [ ${CODE} != 0 ]; then
echo "${RED}Tests failed [code ${CODE}].${TEXTRESET}"
exit ${CODE}
else
echo "${GREEN}Tests succeed.${TEXTRESET}"
fi

View file

@ -1,3 +0,0 @@
#!/usr/bin/env bash
golangci-lint run