diff --git a/.dockerignore b/.dockerignore index 8390d87b6..bcd757988 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,5 @@ dist/ -!dist/traefik +!dist/**/traefik site/ vendor/ .idea/ diff --git a/Dockerfile b/Dockerfile index 873d55312..fea809225 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,13 @@ -FROM scratch -COPY script/ca-certificates.crt /etc/ssl/certs/ -COPY dist/traefik / +# syntax=docker/dockerfile:1.2 +FROM alpine:3.19 + +RUN apk --no-cache --no-progress add ca-certificates tzdata \ + && rm -rf /var/cache/apk/* + +ARG TARGETPLATFORM +COPY ./dist/$TARGETPLATFORM/traefik / + EXPOSE 80 VOLUME ["/tmp"] + ENTRYPOINT ["/traefik"] diff --git a/Makefile b/Makefile index 668c5404e..15565a3ce 100644 --- a/Makefile +++ b/Makefile @@ -7,8 +7,22 @@ VERSION := $(if $(VERSION),$(VERSION),$(VERSION_GIT)) 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 -default: binary +default: generate binary ## Create the "dist" directory dist: @@ -35,43 +49,57 @@ webui/static/index.html: .PHONY: generate-webui generate-webui: webui/static/index.html +## Generate code +.PHONY: generate +generate: + go generate + ## Build the binary .PHONY: binary -binary: generate-webui - ./script/make.sh generate binary +binary: generate-webui dist + @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 -.PHONY: binary-debug -binary-debug: generate-webui - GOOS=linux ./script/make.sh binary +binary-linux-arm64: export GOOS := linux +binary-linux-arm64: export GOARCH := arm64 +binary-linux-arm64: + @$(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) .PHONY: crossbinary-default -crossbinary-default: generate-webui - ./script/make.sh generate crossbinary-default - -## 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 +crossbinary-default: generate generate-webui + $(CURDIR)/script/crossbinary-default.sh ## Run the unit and integration tests .PHONY: test -test: - ./script/make.sh generate test-unit binary test-integration +test: test-unit test-integration ## Run the unit tests .PHONY: 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 .PHONY: test-integration -test-integration: - ./script/make.sh generate binary test-integration +test-integration: binary + 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 pull-images: grep --no-filename -E '^\s+image:' ./integration/resources/compose/*.yml \ @@ -80,38 +108,47 @@ pull-images: | uniq \ | xargs -P 6 -n 1 docker pull -EXECUTABLES = misspell shellcheck +## Lint run golangci-lint +.PHONY: lint +lint: + golangci-lint run ## Validate code and docs .PHONY: validate-files -validate-files: - $(foreach exec,$(EXECUTABLES),\ +validate-files: lint + $(foreach exec,$(LINT_EXECUTABLES),\ $(if $(shell which $(exec)),,$(error "No $(exec) in PATH"))) - ./script/make.sh generate validate-lint validate-misspell - bash $(CURDIR)/script/validate-shell-script.sh + $(CURDIR)/script/validate-misspell.sh + $(CURDIR)/script/validate-shell-script.sh ## Validate code, docs, and vendor .PHONY: validate -validate: +validate: lint $(foreach exec,$(EXECUTABLES),\ $(if $(shell which $(exec)),,$(error "No $(exec) in PATH"))) - ./script/make.sh generate validate-lint validate-misspell validate-vendor - bash $(CURDIR)/script/validate-shell-script.sh + $(CURDIR)/script/validate-vendor.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 .PHONY: build-image -build-image: clean-webui binary - docker build -t $(TRAEFIK_IMAGE) . +build-image: export DOCKER_BUILDX_ARGS := --load +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 -build-image-dirty: binary - docker build -t $(TRAEFIK_IMAGE) . - -## Locally build traefik for linux, then shove it an alpine image, with basic tools. -.PHONY: build-image-debug -build-image-debug: binary-debug - docker build -t $(TRAEFIK_IMAGE) -f debug.Dockerfile . +build-image-dirty: export DOCKER_BUILDX_ARGS := --load +build-image-dirty: export DOCKER_BUILD_PLATFORMS := linux/$(GOARCH) +build-image-dirty: + @$(MAKE) multi-arch-image-latest ## Build documentation site .PHONY: docs @@ -141,30 +178,9 @@ generate-genconf: ## Create packages for the release .PHONY: release-packages release-packages: generate-webui - rm -rf dist - @- $(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/ + $(CURDIR)/script/release-packages.sh ## Format the Code .PHONY: fmt fmt: gofmt -s -l -w $(SRCS) - -.PHONY: run-dev -run-dev: - go generate - GO111MODULE=on go build ./cmd/traefik - ./traefik diff --git a/build.Dockerfile b/build.Dockerfile deleted file mode 100644 index 587424c38..000000000 --- a/build.Dockerfile +++ /dev/null @@ -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 diff --git a/debug.Dockerfile b/debug.Dockerfile deleted file mode 100644 index 4dcf88bf8..000000000 --- a/debug.Dockerfile +++ /dev/null @@ -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"] diff --git a/docs/content/contributing/building-testing.md b/docs/content/contributing/building-testing.md index 838688869..20d05740a 100644 --- a/docs/content/contributing/building-testing.md +++ b/docs/content/contributing/building-testing.md @@ -58,10 +58,12 @@ Once you've set up your go environment and cloned the source repository, you can ```bash $ make binary -./script/make.sh generate binary ----> Making bundle: generate (in .) - ----> Making bundle: binary (in .) +SHA: 8fddfe118288bb5280eb5e77fa952f52def360b4 cheddar 2024-01-11_03:14:57PM +CGO_ENABLED=0 GOGC=off GOOS=darwin GOARCH=arm64 go build -ldflags "-s -w \ + -X github.com/traefik/traefik/v2/pkg/version.Version=8fddfe118288bb5280eb5e77fa952f52def360b4 \ + -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/ traefik* @@ -77,10 +79,7 @@ Run all tests (unit and integration) using the `test` target. ```bash $ make test-unit -./script/make.sh generate test-unit ----> Making bundle: generate (in .) - ----> Making bundle: test-unit (in .) +GOOS=darwin GOARCH=arm64 go test -cover "-coverprofile=cover.out" -v ./pkg/... ./cmd/... + go test -cover -coverprofile=cover.out . ok github.com/traefik/traefik 0.005s coverage: 4.1% of statements diff --git a/docs/content/getting-started/concepts.md b/docs/content/getting-started/concepts.md index 10e1787e4..21e1817f7 100644 --- a/docs/content/getting-started/concepts.md +++ b/docs/content/getting-started/concepts.md @@ -25,7 +25,7 @@ The main features include dynamic configuration, automatic service discovery, an ## 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.). ![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") -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. You no longer need to create and synchronize configuration files cluttered with IP addresses or other rules. diff --git a/docs/content/middlewares/http/compress.md b/docs/content/middlewares/http/compress.md index eec8e73b0..e98954660 100644 --- a/docs/content/middlewares/http/compress.md +++ b/docs/content/middlewares/http/compress.md @@ -55,10 +55,10 @@ http: 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). - 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. * 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`). ## 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. +!!! info + + The `excludedContentTypes` and `includedContentTypes` options are mutually exclusive. + !!! 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. @@ -117,6 +121,59 @@ http: 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` _Optional, Default=1024_ diff --git a/docs/content/middlewares/http/forwardauth.md b/docs/content/middlewares/http/forwardauth.md index 6b69c620b..25b58480c 100644 --- a/docs/content/middlewares/http/forwardauth.md +++ b/docs/content/middlewares/http/forwardauth.md @@ -285,6 +285,55 @@ http: 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` _Optional_ diff --git a/docs/content/reference/dynamic-configuration/docker-labels.yml b/docs/content/reference/dynamic-configuration/docker-labels.yml index 214af5fa1..93a785ff4 100644 --- a/docs/content/reference/dynamic-configuration/docker-labels.yml +++ b/docs/content/reference/dynamic-configuration/docker-labels.yml @@ -1,124 +1,133 @@ -- "traefik.http.middlewares.middleware00.addprefix.prefix=foobar" -- "traefik.http.middlewares.middleware01.basicauth.headerfield=foobar" -- "traefik.http.middlewares.middleware01.basicauth.realm=foobar" -- "traefik.http.middlewares.middleware01.basicauth.removeheader=true" -- "traefik.http.middlewares.middleware01.basicauth.users=foobar, foobar" -- "traefik.http.middlewares.middleware01.basicauth.usersfile=foobar" -- "traefik.http.middlewares.middleware02.buffering.maxrequestbodybytes=42" -- "traefik.http.middlewares.middleware02.buffering.maxresponsebodybytes=42" -- "traefik.http.middlewares.middleware02.buffering.memrequestbodybytes=42" -- "traefik.http.middlewares.middleware02.buffering.memresponsebodybytes=42" -- "traefik.http.middlewares.middleware02.buffering.retryexpression=foobar" -- "traefik.http.middlewares.middleware03.chain.middlewares=foobar, foobar" -- "traefik.http.middlewares.middleware04.circuitbreaker.expression=foobar" -- "traefik.http.middlewares.middleware04.circuitbreaker.checkperiod=42s" -- "traefik.http.middlewares.middleware04.circuitbreaker.fallbackduration=42s" -- "traefik.http.middlewares.middleware04.circuitbreaker.recoveryduration=42s" -- "traefik.http.middlewares.middleware05.compress=true" -- "traefik.http.middlewares.middleware05.compress.excludedcontenttypes=foobar, foobar" -- "traefik.http.middlewares.middleware05.compress.minresponsebodybytes=42" -- "traefik.http.middlewares.middleware06.contenttype=true" -- "traefik.http.middlewares.middleware07.digestauth.headerfield=foobar" -- "traefik.http.middlewares.middleware07.digestauth.realm=foobar" -- "traefik.http.middlewares.middleware07.digestauth.removeheader=true" -- "traefik.http.middlewares.middleware07.digestauth.users=foobar, foobar" -- "traefik.http.middlewares.middleware07.digestauth.usersfile=foobar" -- "traefik.http.middlewares.middleware08.errors.query=foobar" -- "traefik.http.middlewares.middleware08.errors.service=foobar" -- "traefik.http.middlewares.middleware08.errors.status=foobar, foobar" -- "traefik.http.middlewares.middleware09.forwardauth.address=foobar" -- "traefik.http.middlewares.middleware09.forwardauth.authresponseheaders=foobar, foobar" -- "traefik.http.middlewares.middleware09.forwardauth.authresponseheadersregex=foobar" -- "traefik.http.middlewares.middleware09.forwardauth.authrequestheaders=foobar, foobar" -- "traefik.http.middlewares.middleware09.forwardauth.tls.ca=foobar" -- "traefik.http.middlewares.middleware09.forwardauth.tls.cert=foobar" -- "traefik.http.middlewares.middleware09.forwardauth.tls.insecureskipverify=true" -- "traefik.http.middlewares.middleware09.forwardauth.tls.key=foobar" -- "traefik.http.middlewares.middleware09.forwardauth.trustforwardheader=true" -- "traefik.http.middlewares.middleware10.headers.accesscontrolallowcredentials=true" -- "traefik.http.middlewares.middleware10.headers.accesscontrolallowheaders=foobar, foobar" -- "traefik.http.middlewares.middleware10.headers.accesscontrolallowmethods=foobar, foobar" -- "traefik.http.middlewares.middleware10.headers.accesscontrolalloworiginlist=foobar, foobar" -- "traefik.http.middlewares.middleware10.headers.accesscontrolalloworiginlistregex=foobar, foobar" -- "traefik.http.middlewares.middleware10.headers.accesscontrolexposeheaders=foobar, foobar" -- "traefik.http.middlewares.middleware10.headers.accesscontrolmaxage=42" -- "traefik.http.middlewares.middleware10.headers.addvaryheader=true" -- "traefik.http.middlewares.middleware10.headers.allowedhosts=foobar, foobar" -- "traefik.http.middlewares.middleware10.headers.browserxssfilter=true" -- "traefik.http.middlewares.middleware10.headers.contentsecuritypolicy=foobar" -- "traefik.http.middlewares.middleware10.headers.contenttypenosniff=true" -- "traefik.http.middlewares.middleware10.headers.custombrowserxssvalue=foobar" -- "traefik.http.middlewares.middleware10.headers.customframeoptionsvalue=foobar" -- "traefik.http.middlewares.middleware10.headers.customrequestheaders.name0=foobar" -- "traefik.http.middlewares.middleware10.headers.customrequestheaders.name1=foobar" -- "traefik.http.middlewares.middleware10.headers.customresponseheaders.name0=foobar" -- "traefik.http.middlewares.middleware10.headers.customresponseheaders.name1=foobar" -- "traefik.http.middlewares.middleware10.headers.forcestsheader=true" -- "traefik.http.middlewares.middleware10.headers.framedeny=true" -- "traefik.http.middlewares.middleware10.headers.hostsproxyheaders=foobar, foobar" -- "traefik.http.middlewares.middleware10.headers.isdevelopment=true" -- "traefik.http.middlewares.middleware10.headers.permissionspolicy=foobar" -- "traefik.http.middlewares.middleware10.headers.publickey=foobar" -- "traefik.http.middlewares.middleware10.headers.referrerpolicy=foobar" -- "traefik.http.middlewares.middleware10.headers.sslproxyheaders.name0=foobar" -- "traefik.http.middlewares.middleware10.headers.sslproxyheaders.name1=foobar" -- "traefik.http.middlewares.middleware10.headers.stsincludesubdomains=true" -- "traefik.http.middlewares.middleware10.headers.stspreload=true" -- "traefik.http.middlewares.middleware10.headers.stsseconds=42" -- "traefik.http.middlewares.middleware11.ipwhitelist.ipstrategy.depth=42" -- "traefik.http.middlewares.middleware11.ipwhitelist.ipstrategy.excludedips=foobar, foobar" -- "traefik.http.middlewares.middleware12.ipwhitelist.sourcerange=foobar, foobar" -- "traefik.http.middlewares.middleware12.ipallowlist.ipstrategy.depth=42" -- "traefik.http.middlewares.middleware12.ipallowlist.ipstrategy.excludedips=foobar, foobar" -- "traefik.http.middlewares.middleware12.ipallowlist.sourcerange=foobar, foobar" -- "traefik.http.middlewares.middleware12.ipallowlist.rejectstatuscode=404" -- "traefik.http.middlewares.middleware13.inflightreq.amount=42" -- "traefik.http.middlewares.middleware13.inflightreq.sourcecriterion.ipstrategy.depth=42" -- "traefik.http.middlewares.middleware13.inflightreq.sourcecriterion.ipstrategy.excludedips=foobar, foobar" -- "traefik.http.middlewares.middleware13.inflightreq.sourcecriterion.requestheadername=foobar" -- "traefik.http.middlewares.middleware13.inflightreq.sourcecriterion.requesthost=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.issuer.commonname=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.issuer.country=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.issuer.domaincomponent=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.issuer.locality=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.issuer.organization=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.issuer.province=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.issuer.serialnumber=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.notafter=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.notbefore=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.sans=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.serialnumber=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.subject.commonname=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.subject.country=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.subject.domaincomponent=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.subject.locality=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.subject.organization=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.subject.organizationalunit=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.subject.province=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.info.subject.serialnumber=true" -- "traefik.http.middlewares.middleware14.passtlsclientcert.pem=true" -- "traefik.http.middlewares.middleware15.plugin.foobar.foo=bar" -- "traefik.http.middlewares.middleware16.ratelimit.average=42" -- "traefik.http.middlewares.middleware16.ratelimit.burst=42" -- "traefik.http.middlewares.middleware16.ratelimit.period=42" -- "traefik.http.middlewares.middleware16.ratelimit.sourcecriterion.ipstrategy.depth=42" -- "traefik.http.middlewares.middleware16.ratelimit.sourcecriterion.ipstrategy.excludedips=foobar, foobar" -- "traefik.http.middlewares.middleware16.ratelimit.sourcecriterion.requestheadername=foobar" -- "traefik.http.middlewares.middleware16.ratelimit.sourcecriterion.requesthost=true" -- "traefik.http.middlewares.middleware17.redirectregex.permanent=true" -- "traefik.http.middlewares.middleware17.redirectregex.regex=foobar" -- "traefik.http.middlewares.middleware17.redirectregex.replacement=foobar" -- "traefik.http.middlewares.middleware18.redirectscheme.permanent=true" -- "traefik.http.middlewares.middleware18.redirectscheme.port=foobar" -- "traefik.http.middlewares.middleware18.redirectscheme.scheme=foobar" -- "traefik.http.middlewares.middleware19.replacepath.path=foobar" -- "traefik.http.middlewares.middleware20.replacepathregex.regex=foobar" -- "traefik.http.middlewares.middleware20.replacepathregex.replacement=foobar" -- "traefik.http.middlewares.middleware21.retry.attempts=42" -- "traefik.http.middlewares.middleware21.retry.initialinterval=42" -- "traefik.http.middlewares.middleware22.stripprefix.prefixes=foobar, foobar" -- "traefik.http.middlewares.middleware23.stripprefixregex.regex=foobar, foobar" -- "traefik.http.middlewares.middleware24.grpcweb.alloworigins=foobar, foobar" +## CODE GENERATED AUTOMATICALLY +## THIS FILE MUST NOT BE EDITED BY HAND +- "traefik.http.middlewares.middleware01.addprefix.prefix=foobar" +- "traefik.http.middlewares.middleware02.basicauth.headerfield=foobar" +- "traefik.http.middlewares.middleware02.basicauth.realm=foobar" +- "traefik.http.middlewares.middleware02.basicauth.removeheader=true" +- "traefik.http.middlewares.middleware02.basicauth.users=foobar, foobar" +- "traefik.http.middlewares.middleware02.basicauth.usersfile=foobar" +- "traefik.http.middlewares.middleware03.buffering.maxrequestbodybytes=42" +- "traefik.http.middlewares.middleware03.buffering.maxresponsebodybytes=42" +- "traefik.http.middlewares.middleware03.buffering.memrequestbodybytes=42" +- "traefik.http.middlewares.middleware03.buffering.memresponsebodybytes=42" +- "traefik.http.middlewares.middleware03.buffering.retryexpression=foobar" +- "traefik.http.middlewares.middleware04.chain.middlewares=foobar, foobar" +- "traefik.http.middlewares.middleware05.circuitbreaker.checkperiod=42s" +- "traefik.http.middlewares.middleware05.circuitbreaker.expression=foobar" +- "traefik.http.middlewares.middleware05.circuitbreaker.fallbackduration=42s" +- "traefik.http.middlewares.middleware05.circuitbreaker.recoveryduration=42s" +- "traefik.http.middlewares.middleware06.compress=true" +- "traefik.http.middlewares.middleware06.compress.excludedcontenttypes=foobar, foobar" +- "traefik.http.middlewares.middleware06.compress.includedcontenttypes=foobar, foobar" +- "traefik.http.middlewares.middleware06.compress.minresponsebodybytes=42" +- "traefik.http.middlewares.middleware07.contenttype=true" +- "traefik.http.middlewares.middleware08.digestauth.headerfield=foobar" +- "traefik.http.middlewares.middleware08.digestauth.realm=foobar" +- "traefik.http.middlewares.middleware08.digestauth.removeheader=true" +- "traefik.http.middlewares.middleware08.digestauth.users=foobar, foobar" +- "traefik.http.middlewares.middleware08.digestauth.usersfile=foobar" +- "traefik.http.middlewares.middleware09.errors.query=foobar" +- "traefik.http.middlewares.middleware09.errors.service=foobar" +- "traefik.http.middlewares.middleware09.errors.status=foobar, foobar" +- "traefik.http.middlewares.middleware10.forwardauth.addauthcookiestoresponse=foobar, foobar" +- "traefik.http.middlewares.middleware10.forwardauth.address=foobar" +- "traefik.http.middlewares.middleware10.forwardauth.authrequestheaders=foobar, foobar" +- "traefik.http.middlewares.middleware10.forwardauth.authresponseheaders=foobar, foobar" +- "traefik.http.middlewares.middleware10.forwardauth.authresponseheadersregex=foobar" +- "traefik.http.middlewares.middleware10.forwardauth.tls.ca=foobar" +- "traefik.http.middlewares.middleware10.forwardauth.tls.cert=foobar" +- "traefik.http.middlewares.middleware10.forwardauth.tls.insecureskipverify=true" +- "traefik.http.middlewares.middleware10.forwardauth.tls.key=foobar" +- "traefik.http.middlewares.middleware10.forwardauth.trustforwardheader=true" +- "traefik.http.middlewares.middleware11.grpcweb.alloworigins=foobar, foobar" +- "traefik.http.middlewares.middleware12.headers.accesscontrolallowcredentials=true" +- "traefik.http.middlewares.middleware12.headers.accesscontrolallowheaders=foobar, foobar" +- "traefik.http.middlewares.middleware12.headers.accesscontrolallowmethods=foobar, foobar" +- "traefik.http.middlewares.middleware12.headers.accesscontrolalloworiginlist=foobar, foobar" +- "traefik.http.middlewares.middleware12.headers.accesscontrolalloworiginlistregex=foobar, foobar" +- "traefik.http.middlewares.middleware12.headers.accesscontrolexposeheaders=foobar, foobar" +- "traefik.http.middlewares.middleware12.headers.accesscontrolmaxage=42" +- "traefik.http.middlewares.middleware12.headers.addvaryheader=true" +- "traefik.http.middlewares.middleware12.headers.allowedhosts=foobar, foobar" +- "traefik.http.middlewares.middleware12.headers.browserxssfilter=true" +- "traefik.http.middlewares.middleware12.headers.contentsecuritypolicy=foobar" +- "traefik.http.middlewares.middleware12.headers.contenttypenosniff=true" +- "traefik.http.middlewares.middleware12.headers.custombrowserxssvalue=foobar" +- "traefik.http.middlewares.middleware12.headers.customframeoptionsvalue=foobar" +- "traefik.http.middlewares.middleware12.headers.customrequestheaders.name0=foobar" +- "traefik.http.middlewares.middleware12.headers.customrequestheaders.name1=foobar" +- "traefik.http.middlewares.middleware12.headers.customresponseheaders.name0=foobar" +- "traefik.http.middlewares.middleware12.headers.customresponseheaders.name1=foobar" +- "traefik.http.middlewares.middleware12.headers.forcestsheader=true" +- "traefik.http.middlewares.middleware12.headers.framedeny=true" +- "traefik.http.middlewares.middleware12.headers.hostsproxyheaders=foobar, foobar" +- "traefik.http.middlewares.middleware12.headers.isdevelopment=true" +- "traefik.http.middlewares.middleware12.headers.permissionspolicy=foobar" +- "traefik.http.middlewares.middleware12.headers.publickey=foobar" +- "traefik.http.middlewares.middleware12.headers.referrerpolicy=foobar" +- "traefik.http.middlewares.middleware12.headers.sslproxyheaders.name0=foobar" +- "traefik.http.middlewares.middleware12.headers.sslproxyheaders.name1=foobar" +- "traefik.http.middlewares.middleware12.headers.stsincludesubdomains=true" +- "traefik.http.middlewares.middleware12.headers.stspreload=true" +- "traefik.http.middlewares.middleware12.headers.stsseconds=42" +- "traefik.http.middlewares.middleware13.ipallowlist.ipstrategy=true" +- "traefik.http.middlewares.middleware13.ipallowlist.ipstrategy.depth=42" +- "traefik.http.middlewares.middleware13.ipallowlist.ipstrategy.excludedips=foobar, foobar" +- "traefik.http.middlewares.middleware13.ipallowlist.rejectstatuscode=42" +- "traefik.http.middlewares.middleware13.ipallowlist.sourcerange=foobar, foobar" +- "traefik.http.middlewares.middleware14.ipwhitelist.ipstrategy=true" +- "traefik.http.middlewares.middleware14.ipwhitelist.ipstrategy.depth=42" +- "traefik.http.middlewares.middleware14.ipwhitelist.ipstrategy.excludedips=foobar, foobar" +- "traefik.http.middlewares.middleware14.ipwhitelist.sourcerange=foobar, foobar" +- "traefik.http.middlewares.middleware15.inflightreq.amount=42" +- "traefik.http.middlewares.middleware15.inflightreq.sourcecriterion.ipstrategy.depth=42" +- "traefik.http.middlewares.middleware15.inflightreq.sourcecriterion.ipstrategy.excludedips=foobar, foobar" +- "traefik.http.middlewares.middleware15.inflightreq.sourcecriterion.requestheadername=foobar" +- "traefik.http.middlewares.middleware15.inflightreq.sourcecriterion.requesthost=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.issuer.commonname=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.issuer.country=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.issuer.domaincomponent=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.issuer.locality=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.issuer.organization=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.issuer.province=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.issuer.serialnumber=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.notafter=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.notbefore=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.sans=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.serialnumber=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.subject.commonname=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.subject.country=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.subject.domaincomponent=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.subject.locality=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.subject.organization=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.subject.organizationalunit=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.subject.province=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.info.subject.serialnumber=true" +- "traefik.http.middlewares.middleware16.passtlsclientcert.pem=true" +- "traefik.http.middlewares.middleware17.plugin.pluginconf0.name0=foobar" +- "traefik.http.middlewares.middleware17.plugin.pluginconf0.name1=foobar" +- "traefik.http.middlewares.middleware17.plugin.pluginconf1.name0=foobar" +- "traefik.http.middlewares.middleware17.plugin.pluginconf1.name1=foobar" +- "traefik.http.middlewares.middleware18.ratelimit.average=42" +- "traefik.http.middlewares.middleware18.ratelimit.burst=42" +- "traefik.http.middlewares.middleware18.ratelimit.period=42s" +- "traefik.http.middlewares.middleware18.ratelimit.sourcecriterion.ipstrategy.depth=42" +- "traefik.http.middlewares.middleware18.ratelimit.sourcecriterion.ipstrategy.excludedips=foobar, foobar" +- "traefik.http.middlewares.middleware18.ratelimit.sourcecriterion.requestheadername=foobar" +- "traefik.http.middlewares.middleware18.ratelimit.sourcecriterion.requesthost=true" +- "traefik.http.middlewares.middleware19.redirectregex.permanent=true" +- "traefik.http.middlewares.middleware19.redirectregex.regex=foobar" +- "traefik.http.middlewares.middleware19.redirectregex.replacement=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.middlewares=foobar, foobar" - "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].sans=foobar, foobar" - "traefik.http.routers.router1.tls.options=foobar" -- "traefik.http.services.service01.loadbalancer.healthcheck.followredirects=true" -- "traefik.http.services.service01.loadbalancer.healthcheck.headers.name0=foobar" -- "traefik.http.services.service01.loadbalancer.healthcheck.headers.name1=foobar" -- "traefik.http.services.service01.loadbalancer.healthcheck.hostname=foobar" -- "traefik.http.services.service01.loadbalancer.healthcheck.interval=foobar" -- "traefik.http.services.service01.loadbalancer.healthcheck.path=foobar" -- "traefik.http.services.service01.loadbalancer.healthcheck.method=foobar" -- "traefik.http.services.service01.loadbalancer.healthcheck.status=42" -- "traefik.http.services.service01.loadbalancer.healthcheck.port=42" -- "traefik.http.services.service01.loadbalancer.healthcheck.scheme=foobar" -- "traefik.http.services.service01.loadbalancer.healthcheck.mode=foobar" -- "traefik.http.services.service01.loadbalancer.healthcheck.timeout=foobar" -- "traefik.http.services.service01.loadbalancer.passhostheader=true" -- "traefik.http.services.service01.loadbalancer.responseforwarding.flushinterval=foobar" -- "traefik.http.services.service01.loadbalancer.serverstransport=foobar" -- "traefik.http.services.service01.loadbalancer.sticky.cookie=true" -- "traefik.http.services.service01.loadbalancer.sticky.cookie.httponly=true" -- "traefik.http.services.service01.loadbalancer.sticky.cookie.name=foobar" -- "traefik.http.services.service01.loadbalancer.sticky.cookie.samesite=foobar" -- "traefik.http.services.service01.loadbalancer.sticky.cookie.secure=true" -- "traefik.http.services.service01.loadbalancer.server.port=foobar" -- "traefik.http.services.service01.loadbalancer.server.scheme=foobar" -- "traefik.tcp.middlewares.tcpmiddleware00.inflightconn.amount=42" -- "traefik.tcp.middlewares.tcpmiddleware01.ipwhitelist.sourcerange=foobar, foobar" -- "traefik.tcp.middlewares.tcpmiddleware02.ipallowlist.sourcerange=foobar, foobar" +- "traefik.http.services.service02.loadbalancer.healthcheck.followredirects=true" +- "traefik.http.services.service02.loadbalancer.healthcheck.headers.name0=foobar" +- "traefik.http.services.service02.loadbalancer.healthcheck.headers.name1=foobar" +- "traefik.http.services.service02.loadbalancer.healthcheck.hostname=foobar" +- "traefik.http.services.service02.loadbalancer.healthcheck.interval=42s" +- "traefik.http.services.service02.loadbalancer.healthcheck.method=foobar" +- "traefik.http.services.service02.loadbalancer.healthcheck.mode=foobar" +- "traefik.http.services.service02.loadbalancer.healthcheck.path=foobar" +- "traefik.http.services.service02.loadbalancer.healthcheck.port=42" +- "traefik.http.services.service02.loadbalancer.healthcheck.scheme=foobar" +- "traefik.http.services.service02.loadbalancer.healthcheck.status=42" +- "traefik.http.services.service02.loadbalancer.healthcheck.timeout=42s" +- "traefik.http.services.service02.loadbalancer.passhostheader=true" +- "traefik.http.services.service02.loadbalancer.responseforwarding.flushinterval=42s" +- "traefik.http.services.service02.loadbalancer.serverstransport=foobar" +- "traefik.http.services.service02.loadbalancer.sticky=true" +- "traefik.http.services.service02.loadbalancer.sticky.cookie=true" +- "traefik.http.services.service02.loadbalancer.sticky.cookie.httponly=true" +- "traefik.http.services.service02.loadbalancer.sticky.cookie.maxage=42" +- "traefik.http.services.service02.loadbalancer.sticky.cookie.name=foobar" +- "traefik.http.services.service02.loadbalancer.sticky.cookie.samesite=foobar" +- "traefik.http.services.service02.loadbalancer.sticky.cookie.secure=true" +- "traefik.http.services.service02.loadbalancer.server.port=foobar" +- "traefik.http.services.service02.loadbalancer.server.scheme=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.middlewares=foobar, foobar" -- "traefik.tcp.routers.tcprouter0.rule=foobar" - "traefik.tcp.routers.tcprouter0.priority=42" +- "traefik.tcp.routers.tcprouter0.rule=foobar" - "traefik.tcp.routers.tcprouter0.service=foobar" - "traefik.tcp.routers.tcprouter0.tls=true" - "traefik.tcp.routers.tcprouter0.tls.certresolver=foobar" @@ -183,8 +194,8 @@ - "traefik.tcp.routers.tcprouter0.tls.passthrough=true" - "traefik.tcp.routers.tcprouter1.entrypoints=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.rule=foobar" - "traefik.tcp.routers.tcprouter1.service=foobar" - "traefik.tcp.routers.tcprouter1.tls=true" - "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.options=foobar" - "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.serverstransport=foobar" - "traefik.tcp.services.tcpservice01.loadbalancer.server.port=foobar" - "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.service=foobar" - "traefik.udp.routers.udprouter1.entrypoints=foobar, foobar" - "traefik.udp.routers.udprouter1.service=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" diff --git a/docs/content/reference/dynamic-configuration/file.toml b/docs/content/reference/dynamic-configuration/file.toml index 49cf27e95..a8264d2ed 100644 --- a/docs/content/reference/dynamic-configuration/file.toml +++ b/docs/content/reference/dynamic-configuration/file.toml @@ -1,3 +1,5 @@ +## CODE GENERATED AUTOMATICALLY +## THIS FILE MUST NOT BE EDITED BY HAND [http] [http.routers] [http.routers.Router0] @@ -36,22 +38,28 @@ sans = ["foobar", "foobar"] [http.services] [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 serversTransport = "foobar" - [http.services.Service01.loadBalancer.sticky] - [http.services.Service01.loadBalancer.sticky.cookie] + [http.services.Service02.loadBalancer.sticky] + [http.services.Service02.loadBalancer.sticky.cookie] name = "foobar" secure = true httpOnly = true sameSite = "foobar" + maxAge = 42 - [[http.services.Service01.loadBalancer.servers]] + [[http.services.Service02.loadBalancer.servers]] url = "foobar" - [[http.services.Service01.loadBalancer.servers]] + [[http.services.Service02.loadBalancer.servers]] url = "foobar" - [http.services.Service01.loadBalancer.healthCheck] + [http.services.Service02.loadBalancer.healthCheck] scheme = "foobar" mode = "foobar" path = "foobar" @@ -62,107 +70,106 @@ timeout = "42s" hostname = "foobar" followRedirects = true - [http.services.Service01.loadBalancer.healthCheck.headers] + [http.services.Service02.loadBalancer.healthCheck.headers] name0 = "foobar" name1 = "foobar" - [http.services.Service01.loadBalancer.responseForwarding] + [http.services.Service02.loadBalancer.responseForwarding] flushInterval = "42s" - [http.services.Service02] - [http.services.Service02.mirroring] + [http.services.Service03] + [http.services.Service03.mirroring] service = "foobar" maxBodySize = 42 - [http.services.Service02.mirroring.healthCheck] - - [[http.services.Service02.mirroring.mirrors]] + [[http.services.Service03.mirroring.mirrors]] name = "foobar" percent = 42 - [[http.services.Service02.mirroring.mirrors]] + [[http.services.Service03.mirroring.mirrors]] name = "foobar" percent = 42 - [http.services.Service03] - [http.services.Service03.weighted] - [http.services.Service03.weighted.healthCheck] + [http.services.Service03.mirroring.healthCheck] + [http.services.Service04] + [http.services.Service04.weighted] - [[http.services.Service03.weighted.services]] + [[http.services.Service04.weighted.services]] name = "foobar" weight = 42 - [[http.services.Service03.weighted.services]] + [[http.services.Service04.weighted.services]] name = "foobar" weight = 42 - [http.services.Service03.weighted.sticky] - [http.services.Service03.weighted.sticky.cookie] + [http.services.Service04.weighted.sticky] + [http.services.Service04.weighted.sticky.cookie] name = "foobar" secure = true httpOnly = true sameSite = "foobar" - [http.services.Service04] - [http.services.Service04.failover] - service = "foobar" - fallback = "foobar" - - [http.services.Service04.failover.healthCheck] + maxAge = 42 + [http.services.Service04.weighted.healthCheck] [http.middlewares] - [http.middlewares.Middleware00] - [http.middlewares.Middleware00.addPrefix] - prefix = "foobar" [http.middlewares.Middleware01] - [http.middlewares.Middleware01.basicAuth] + [http.middlewares.Middleware01.addPrefix] + prefix = "foobar" + [http.middlewares.Middleware02] + [http.middlewares.Middleware02.basicAuth] users = ["foobar", "foobar"] usersFile = "foobar" realm = "foobar" removeHeader = true headerField = "foobar" - [http.middlewares.Middleware02] - [http.middlewares.Middleware02.buffering] + [http.middlewares.Middleware03] + [http.middlewares.Middleware03.buffering] maxRequestBodyBytes = 42 memRequestBodyBytes = 42 maxResponseBodyBytes = 42 memResponseBodyBytes = 42 retryExpression = "foobar" - [http.middlewares.Middleware03] - [http.middlewares.Middleware03.chain] - middlewares = ["foobar", "foobar"] [http.middlewares.Middleware04] - [http.middlewares.Middleware04.circuitBreaker] + [http.middlewares.Middleware04.chain] + middlewares = ["foobar", "foobar"] + [http.middlewares.Middleware05] + [http.middlewares.Middleware05.circuitBreaker] expression = "foobar" checkPeriod = "42s" fallbackDuration = "42s" recoveryDuration = "42s" - [http.middlewares.Middleware05] - [http.middlewares.Middleware05.compress] - excludedContentTypes = ["foobar", "foobar"] - minResponseBodyBytes = 42 [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.digestAuth] + [http.middlewares.Middleware07.contentType] + [http.middlewares.Middleware08] + [http.middlewares.Middleware08.digestAuth] users = ["foobar", "foobar"] usersFile = "foobar" removeHeader = true realm = "foobar" headerField = "foobar" - [http.middlewares.Middleware08] - [http.middlewares.Middleware08.errors] + [http.middlewares.Middleware09] + [http.middlewares.Middleware09.errors] status = ["foobar", "foobar"] service = "foobar" query = "foobar" - [http.middlewares.Middleware09] - [http.middlewares.Middleware09.forwardAuth] + [http.middlewares.Middleware10] + [http.middlewares.Middleware10.forwardAuth] address = "foobar" trustForwardHeader = true authResponseHeaders = ["foobar", "foobar"] authResponseHeadersRegex = "foobar" authRequestHeaders = ["foobar", "foobar"] - [http.middlewares.Middleware09.forwardAuth.tls] + addAuthCookiesToResponse = ["foobar", "foobar"] + [http.middlewares.Middleware10.forwardAuth.tls] ca = "foobar" cert = "foobar" key = "foobar" insecureSkipVerify = true - [http.middlewares.Middleware10] - [http.middlewares.Middleware10.headers] + [http.middlewares.Middleware11] + [http.middlewares.Middleware11.grpcWeb] + allowOrigins = ["foobar", "foobar"] + [http.middlewares.Middleware12] + [http.middlewares.Middleware12.headers] accessControlAllowCredentials = true accessControlAllowHeaders = ["foobar", "foobar"] accessControlAllowMethods = ["foobar", "foobar"] @@ -187,46 +194,46 @@ referrerPolicy = "foobar" permissionsPolicy = "foobar" isDevelopment = true - [http.middlewares.Middleware10.headers.customRequestHeaders] + [http.middlewares.Middleware12.headers.customRequestHeaders] name0 = "foobar" name1 = "foobar" - [http.middlewares.Middleware10.headers.customResponseHeaders] + [http.middlewares.Middleware12.headers.customResponseHeaders] name0 = "foobar" name1 = "foobar" - [http.middlewares.Middleware10.headers.sslProxyHeaders] + [http.middlewares.Middleware12.headers.sslProxyHeaders] name0 = "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.inFlightReq] + [http.middlewares.Middleware13.ipAllowList] + sourceRange = ["foobar", "foobar"] + rejectStatusCode = 42 + [http.middlewares.Middleware13.ipAllowList.ipStrategy] + depth = 42 + excludedIPs = ["foobar", "foobar"] + [http.middlewares.Middleware14] + [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.Middleware13.inFlightReq.sourceCriterion] + [http.middlewares.Middleware15.inFlightReq.sourceCriterion] requestHeaderName = "foobar" requestHost = true - [http.middlewares.Middleware13.inFlightReq.sourceCriterion.ipStrategy] + [http.middlewares.Middleware15.inFlightReq.sourceCriterion.ipStrategy] depth = 42 excludedIPs = ["foobar", "foobar"] - [http.middlewares.Middleware14] - [http.middlewares.Middleware14.passTLSClientCert] + [http.middlewares.Middleware16] + [http.middlewares.Middleware16.passTLSClientCert] pem = true - [http.middlewares.Middleware14.passTLSClientCert.info] + [http.middlewares.Middleware16.passTLSClientCert.info] notAfter = true notBefore = true sans = true serialNumber = true - [http.middlewares.Middleware14.passTLSClientCert.info.subject] + [http.middlewares.Middleware16.passTLSClientCert.info.subject] country = true province = true locality = true @@ -235,7 +242,7 @@ commonName = true serialNumber = true domainComponent = true - [http.middlewares.Middleware14.passTLSClientCert.info.issuer] + [http.middlewares.Middleware16.passTLSClientCert.info.issuer] country = true province = true locality = true @@ -243,51 +250,52 @@ commonName = true serialNumber = true domainComponent = true - [http.middlewares.Middleware15] - [http.middlewares.Middleware15.plugin] - [http.middlewares.Middleware15.plugin.PluginConf] - foo = "bar" - [http.middlewares.Middleware16] - [http.middlewares.Middleware16.rateLimit] + [http.middlewares.Middleware17] + [http.middlewares.Middleware17.plugin] + [http.middlewares.Middleware17.plugin.PluginConf0] + name0 = "foobar" + name1 = "foobar" + [http.middlewares.Middleware17.plugin.PluginConf1] + name0 = "foobar" + name1 = "foobar" + [http.middlewares.Middleware18] + [http.middlewares.Middleware18.rateLimit] average = 42 period = "42s" burst = 42 - [http.middlewares.Middleware16.rateLimit.sourceCriterion] + [http.middlewares.Middleware18.rateLimit.sourceCriterion] requestHeaderName = "foobar" requestHost = true - [http.middlewares.Middleware16.rateLimit.sourceCriterion.ipStrategy] + [http.middlewares.Middleware18.rateLimit.sourceCriterion.ipStrategy] depth = 42 excludedIPs = ["foobar", "foobar"] - [http.middlewares.Middleware17] - [http.middlewares.Middleware17.redirectRegex] + [http.middlewares.Middleware19] + [http.middlewares.Middleware19.redirectRegex] regex = "foobar" replacement = "foobar" permanent = true - [http.middlewares.Middleware18] - [http.middlewares.Middleware18.redirectScheme] + [http.middlewares.Middleware20] + [http.middlewares.Middleware20.redirectScheme] scheme = "foobar" port = "foobar" permanent = true - [http.middlewares.Middleware19] - [http.middlewares.Middleware19.replacePath] + [http.middlewares.Middleware21] + [http.middlewares.Middleware21.replacePath] path = "foobar" - [http.middlewares.Middleware20] - [http.middlewares.Middleware20.replacePathRegex] + [http.middlewares.Middleware22] + [http.middlewares.Middleware22.replacePathRegex] regex = "foobar" replacement = "foobar" - [http.middlewares.Middleware21] - [http.middlewares.Middleware21.retry] + [http.middlewares.Middleware23] + [http.middlewares.Middleware23.retry] attempts = 42 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.grpcWeb] - allowOrigins = ["foobar", "foobar"] + [http.middlewares.Middleware24.stripPrefix] + prefixes = ["foobar", "foobar"] + [http.middlewares.Middleware25] + [http.middlewares.Middleware25.stripPrefixRegex] + regex = ["foobar", "foobar"] [http.serversTransports] [http.serversTransports.ServersTransport0] serverName = "foobar" @@ -304,18 +312,15 @@ [[http.serversTransports.ServersTransport0.certificates]] certFile = "foobar" keyFile = "foobar" - [http.serversTransports.ServersTransport0.forwardingTimeouts] dialTimeout = "42s" responseHeaderTimeout = "42s" idleConnTimeout = "42s" readIdleTimeout = "42s" pingTimeout = "42s" - [http.serversTransports.ServersTransport0.spiffe] ids = ["foobar", "foobar"] trustDomain = "foobar" - [http.serversTransports.ServersTransport1] serverName = "foobar" insecureSkipVerify = true @@ -331,14 +336,12 @@ [[http.serversTransports.ServersTransport1.certificates]] certFile = "foobar" keyFile = "foobar" - [http.serversTransports.ServersTransport1.forwardingTimeouts] dialTimeout = "42s" responseHeaderTimeout = "42s" idleConnTimeout = "42s" readIdleTimeout = "42s" pingTimeout = "42s" - [http.serversTransports.ServersTransport1.spiffe] ids = ["foobar", "foobar"] trustDomain = "foobar" @@ -405,21 +408,21 @@ [[tcp.services.TCPService02.weighted.services]] name = "foobar" weight = 42 - [tcp.middlewares] - [tcp.middlewares.TCPMiddleware00] - [tcp.middlewares.TCPMiddleware00.ipAllowList] - sourceRange = ["foobar", "foobar"] [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 - [tcp.serversTransports] [tcp.serversTransports.TCPServersTransport0] - dialTimeout = "42s" dialKeepAlive = "42s" + dialTimeout = "42s" terminationDelay = "42s" - [tcp.serversTransports.TCPServersTransport0.tls] serverName = "foobar" insecureSkipVerify = true @@ -433,16 +436,13 @@ [[tcp.serversTransports.TCPServersTransport0.tls.certificates]] certFile = "foobar" keyFile = "foobar" - - [tcp.serversTransports.TCPServersTransport0.spiffe] - ids = ["foobar", "foobar"] - trustDomain = "foobar" - + [tcp.serversTransports.TCPServersTransport0.tls.spiffe] + ids = ["foobar", "foobar"] + trustDomain = "foobar" [tcp.serversTransports.TCPServersTransport1] - dialTimeout = "42s" dialKeepAlive = "42s" + dialTimeout = "42s" terminationDelay = "42s" - [tcp.serversTransports.TCPServersTransport1.tls] serverName = "foobar" insecureSkipVerify = true @@ -456,10 +456,9 @@ [[tcp.serversTransports.TCPServersTransport1.tls.certificates]] certFile = "foobar" keyFile = "foobar" - - [tcp.serversTransports.TCPServersTransport1.spiffe] - ids = ["foobar", "foobar"] - trustDomain = "foobar" + [tcp.serversTransports.TCPServersTransport1.tls.spiffe] + ids = ["foobar", "foobar"] + trustDomain = "foobar" [udp] [udp.routers] diff --git a/docs/content/reference/dynamic-configuration/file.yaml b/docs/content/reference/dynamic-configuration/file.yaml index a1bd21658..7ae72ad7d 100644 --- a/docs/content/reference/dynamic-configuration/file.yaml +++ b/docs/content/reference/dynamic-configuration/file.yaml @@ -1,3 +1,5 @@ +## CODE GENERATED AUTOMATICALLY +## THIS FILE MUST NOT BE EDITED BY HAND http: routers: Router0: @@ -46,6 +48,11 @@ http: - foobar services: Service01: + failover: + service: foobar + fallback: foobar + healthCheck: {} + Service02: loadBalancer: sticky: cookie: @@ -53,6 +60,7 @@ http: secure: true httpOnly: true sameSite: foobar + maxAge: 42 servers: - url: foobar - url: foobar @@ -74,19 +82,18 @@ http: responseForwarding: flushInterval: 42s serversTransport: foobar - Service02: + Service03: mirroring: service: foobar maxBodySize: 42 - healthCheck: {} mirrors: - name: foobar percent: 42 - name: foobar percent: 42 - Service03: - weighted: healthCheck: {} + Service04: + weighted: services: - name: foobar weight: 42 @@ -98,16 +105,13 @@ http: secure: true httpOnly: true sameSite: foobar - Service04: - failover: - service: foobar - fallback: foobar + maxAge: 42 healthCheck: {} middlewares: - Middleware00: + Middleware01: addPrefix: prefix: foobar - Middleware01: + Middleware02: basicAuth: users: - foobar @@ -116,33 +120,36 @@ http: realm: foobar removeHeader: true headerField: foobar - Middleware02: + Middleware03: buffering: maxRequestBodyBytes: 42 memRequestBodyBytes: 42 maxResponseBodyBytes: 42 memResponseBodyBytes: 42 retryExpression: foobar - Middleware03: + Middleware04: chain: middlewares: - foobar - foobar - Middleware04: + Middleware05: circuitBreaker: expression: foobar checkPeriod: 42s fallbackDuration: 42s recoveryDuration: 42s - Middleware05: + Middleware06: compress: excludedContentTypes: - foobar - foobar + includedContentTypes: + - foobar + - foobar minResponseBodyBytes: 42 - Middleware06: - contentType: {} Middleware07: + contentType: {} + Middleware08: digestAuth: users: - foobar @@ -151,14 +158,14 @@ http: removeHeader: true realm: foobar headerField: foobar - Middleware08: + Middleware09: errors: status: - foobar - foobar service: foobar query: foobar - Middleware09: + Middleware10: forwardAuth: address: foobar tls: @@ -174,7 +181,15 @@ http: authRequestHeaders: - foobar - foobar - Middleware10: + addAuthCookiesToResponse: + - foobar + - foobar + Middleware11: + grpcWeb: + allowOrigins: + - foobar + - foobar + Middleware12: headers: customRequestHeaders: name0: foobar @@ -223,7 +238,18 @@ http: referrerPolicy: foobar permissionsPolicy: foobar isDevelopment: true - Middleware11: + Middleware13: + ipAllowList: + sourceRange: + - foobar + - foobar + ipStrategy: + depth: 42 + excludedIPs: + - foobar + - foobar + rejectStatusCode: 42 + Middleware14: ipWhiteList: sourceRange: - foobar @@ -233,18 +259,7 @@ http: excludedIPs: - foobar - foobar - Middleware12: - ipAllowList: - rejectStatusCode: 404 - sourceRange: - - foobar - - foobar - ipStrategy: - depth: 42 - excludedIPs: - - foobar - - foobar - Middleware13: + Middleware15: inFlightReq: amount: 42 sourceCriterion: @@ -255,13 +270,14 @@ http: - foobar requestHeaderName: foobar requestHost: true - Middleware14: + Middleware16: passTLSClientCert: pem: true info: notAfter: true notBefore: true sans: true + serialNumber: true subject: country: true province: true @@ -279,12 +295,15 @@ http: commonName: true serialNumber: true domainComponent: true - serialNumber: true - Middleware15: + Middleware17: plugin: - PluginConf: - foo: bar - Middleware16: + PluginConf0: + name0: foobar + name1: foobar + PluginConf1: + name0: foobar + name1: foobar + Middleware18: rateLimit: average: 42 period: 42s @@ -297,42 +316,37 @@ http: - foobar requestHeaderName: foobar requestHost: true - Middleware17: + Middleware19: redirectRegex: regex: foobar replacement: foobar permanent: true - Middleware18: + Middleware20: redirectScheme: scheme: foobar port: foobar permanent: true - Middleware19: + Middleware21: replacePath: path: foobar - Middleware20: + Middleware22: replacePathRegex: regex: foobar replacement: foobar - Middleware21: + Middleware23: retry: attempts: 42 initialInterval: 42s - Middleware22: + Middleware24: stripPrefix: prefixes: - foobar - foobar - Middleware23: + Middleware25: stripPrefixRegex: regex: - foobar - foobar - Middleware24: - grpcWeb: - allowOrigins: - - foobar - - foobar serversTransports: ServersTransport0: serverName: foobar @@ -359,7 +373,6 @@ http: - foobar - foobar trustDomain: foobar - ServersTransport1: serverName: foobar insecureSkipVerify: true @@ -385,7 +398,6 @@ http: - foobar - foobar trustDomain: foobar - tcp: routers: TCPRouter0: @@ -437,7 +449,6 @@ tcp: services: TCPService01: loadBalancer: - serversTransport: foobar proxyProtocol: version: 42 servers: @@ -445,6 +456,7 @@ tcp: tls: true - address: foobar tls: true + serversTransport: foobar TCPService02: weighted: services: @@ -453,23 +465,23 @@ tcp: - name: foobar weight: 42 middlewares: - TCPMiddleware00: + TCPMiddleware01: ipAllowList: sourceRange: - foobar - foobar - TCPMiddleware01: + TCPMiddleware02: + ipWhiteList: + sourceRange: + - foobar + - foobar + TCPMiddleware03: inFlightConn: amount: 42 - TCPMiddleware02: - ipAllowList: - sourceRange: - - foobar - - foobar serversTransports: TCPServersTransport0: - dialTimeout: 42s dialKeepAlive: 42s + dialTimeout: 42s terminationDelay: 42s tls: serverName: foobar @@ -483,14 +495,14 @@ tcp: - certFile: foobar keyFile: foobar peerCertURI: foobar - spiffe: - ids: - - foobar - - foobar - trustDomain: foobar + spiffe: + ids: + - foobar + - foobar + trustDomain: foobar TCPServersTransport1: - dialTimeout: 42s dialKeepAlive: 42s + dialTimeout: 42s terminationDelay: 42s tls: serverName: foobar @@ -504,11 +516,11 @@ tcp: - certFile: foobar keyFile: foobar peerCertURI: foobar - spiffe: - ids: - - foobar - - foobar - trustDomain: foobar + spiffe: + ids: + - foobar + - foobar + trustDomain: foobar udp: routers: UDPRouter0: diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml index e388639a9..5a4c63c3c 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml @@ -160,6 +160,12 @@ spec: can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string @@ -750,6 +756,13 @@ spec: items: type: string 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: description: 'MinResponseBodyBytes defines the minimum amount of bytes a response body must have to be compressed. Default: @@ -870,6 +883,12 @@ spec: description: HTTPOnly defines whether the cookie can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string @@ -912,6 +931,12 @@ spec: This middleware delegates the request authentication to a Service. More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/forwardauth/' 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: description: Address defines the authentication server address. type: string @@ -2145,6 +2170,12 @@ spec: description: HTTPOnly defines whether the cookie can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string @@ -2236,6 +2267,12 @@ spec: description: HTTPOnly defines whether the cookie can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string @@ -2343,6 +2380,12 @@ spec: description: HTTPOnly defines whether the cookie can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string @@ -2382,6 +2425,12 @@ spec: description: HTTPOnly defines whether the cookie can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string diff --git a/docs/content/reference/dynamic-configuration/kv-ref.md b/docs/content/reference/dynamic-configuration/kv-ref.md index 13ed064b2..f078b166a 100644 --- a/docs/content/reference/dynamic-configuration/kv-ref.md +++ b/docs/content/reference/dynamic-configuration/kv-ref.md @@ -1,146 +1,157 @@ -| `traefik/http/middlewares/Middleware00/addPrefix/prefix` | `foobar` | -| `traefik/http/middlewares/Middleware01/basicAuth/headerField` | `foobar` | -| `traefik/http/middlewares/Middleware01/basicAuth/realm` | `foobar` | -| `traefik/http/middlewares/Middleware01/basicAuth/removeHeader` | `true` | -| `traefik/http/middlewares/Middleware01/basicAuth/users/0` | `foobar` | -| `traefik/http/middlewares/Middleware01/basicAuth/users/1` | `foobar` | -| `traefik/http/middlewares/Middleware01/basicAuth/usersFile` | `foobar` | -| `traefik/http/middlewares/Middleware02/buffering/maxRequestBodyBytes` | `42` | -| `traefik/http/middlewares/Middleware02/buffering/maxResponseBodyBytes` | `42` | -| `traefik/http/middlewares/Middleware02/buffering/memRequestBodyBytes` | `42` | -| `traefik/http/middlewares/Middleware02/buffering/memResponseBodyBytes` | `42` | -| `traefik/http/middlewares/Middleware02/buffering/retryExpression` | `foobar` | -| `traefik/http/middlewares/Middleware03/chain/middlewares/0` | `foobar` | -| `traefik/http/middlewares/Middleware03/chain/middlewares/1` | `foobar` | -| `traefik/http/middlewares/Middleware04/circuitBreaker/checkPeriod` | `42s` | -| `traefik/http/middlewares/Middleware04/circuitBreaker/expression` | `foobar` | -| `traefik/http/middlewares/Middleware04/circuitBreaker/fallbackDuration` | `42s` | -| `traefik/http/middlewares/Middleware04/circuitBreaker/recoveryDuration` | `42s` | -| `traefik/http/middlewares/Middleware05/compress/excludedContentTypes/0` | `foobar` | -| `traefik/http/middlewares/Middleware05/compress/excludedContentTypes/1` | `foobar` | -| `traefik/http/middlewares/Middleware05/compress/minResponseBodyBytes` | `42` | -| `traefik/http/middlewares/Middleware06/contentType` | `` | -| `traefik/http/middlewares/Middleware07/digestAuth/headerField` | `foobar` | -| `traefik/http/middlewares/Middleware07/digestAuth/realm` | `foobar` | -| `traefik/http/middlewares/Middleware07/digestAuth/removeHeader` | `true` | -| `traefik/http/middlewares/Middleware07/digestAuth/users/0` | `foobar` | -| `traefik/http/middlewares/Middleware07/digestAuth/users/1` | `foobar` | -| `traefik/http/middlewares/Middleware07/digestAuth/usersFile` | `foobar` | -| `traefik/http/middlewares/Middleware08/errors/query` | `foobar` | -| `traefik/http/middlewares/Middleware08/errors/service` | `foobar` | -| `traefik/http/middlewares/Middleware08/errors/status/0` | `foobar` | -| `traefik/http/middlewares/Middleware08/errors/status/1` | `foobar` | -| `traefik/http/middlewares/Middleware09/forwardAuth/address` | `foobar` | -| `traefik/http/middlewares/Middleware09/forwardAuth/authRequestHeaders/0` | `foobar` | -| `traefik/http/middlewares/Middleware09/forwardAuth/authRequestHeaders/1` | `foobar` | -| `traefik/http/middlewares/Middleware09/forwardAuth/authResponseHeaders/0` | `foobar` | -| `traefik/http/middlewares/Middleware09/forwardAuth/authResponseHeaders/1` | `foobar` | -| `traefik/http/middlewares/Middleware09/forwardAuth/authResponseHeadersRegex` | `foobar` | -| `traefik/http/middlewares/Middleware09/forwardAuth/tls/ca` | `foobar` | -| `traefik/http/middlewares/Middleware09/forwardAuth/tls/cert` | `foobar` | -| `traefik/http/middlewares/Middleware09/forwardAuth/tls/insecureSkipVerify` | `true` | -| `traefik/http/middlewares/Middleware09/forwardAuth/tls/key` | `foobar` | -| `traefik/http/middlewares/Middleware09/forwardAuth/trustForwardHeader` | `true` | -| `traefik/http/middlewares/Middleware10/headers/accessControlAllowCredentials` | `true` | -| `traefik/http/middlewares/Middleware10/headers/accessControlAllowHeaders/0` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/accessControlAllowHeaders/1` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/accessControlAllowMethods/0` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/accessControlAllowMethods/1` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/accessControlAllowOriginList/0` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/accessControlAllowOriginList/1` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/accessControlAllowOriginListRegex/0` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/accessControlAllowOriginListRegex/1` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/accessControlExposeHeaders/0` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/accessControlExposeHeaders/1` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/accessControlMaxAge` | `42` | -| `traefik/http/middlewares/Middleware10/headers/addVaryHeader` | `true` | -| `traefik/http/middlewares/Middleware10/headers/allowedHosts/0` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/allowedHosts/1` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/browserXssFilter` | `true` | -| `traefik/http/middlewares/Middleware10/headers/contentSecurityPolicy` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/contentTypeNosniff` | `true` | -| `traefik/http/middlewares/Middleware10/headers/customBrowserXSSValue` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/customFrameOptionsValue` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/customRequestHeaders/name0` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/customRequestHeaders/name1` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/customResponseHeaders/name0` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/customResponseHeaders/name1` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/forceSTSHeader` | `true` | -| `traefik/http/middlewares/Middleware10/headers/frameDeny` | `true` | -| `traefik/http/middlewares/Middleware10/headers/hostsProxyHeaders/0` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/hostsProxyHeaders/1` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/isDevelopment` | `true` | -| `traefik/http/middlewares/Middleware10/headers/permissionsPolicy` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/publicKey` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/referrerPolicy` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/sslProxyHeaders/name0` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/sslProxyHeaders/name1` | `foobar` | -| `traefik/http/middlewares/Middleware10/headers/stsIncludeSubdomains` | `true` | -| `traefik/http/middlewares/Middleware10/headers/stsPreload` | `true` | -| `traefik/http/middlewares/Middleware10/headers/stsSeconds` | `42` | -| `traefik/http/middlewares/Middleware11/ipWhiteList/ipStrategy/depth` | `42` | -| `traefik/http/middlewares/Middleware11/ipWhiteList/ipStrategy/excludedIPs/0` | `foobar` | -| `traefik/http/middlewares/Middleware11/ipWhiteList/ipStrategy/excludedIPs/1` | `foobar` | -| `traefik/http/middlewares/Middleware11/ipWhiteList/sourceRange/0` | `foobar` | -| `traefik/http/middlewares/Middleware11/ipWhiteList/sourceRange/1` | `foobar` | -| `traefik/http/middlewares/Middleware12/ipAllowList/ipStrategy/depth` | `42` | -| `traefik/http/middlewares/Middleware12/ipAllowList/ipStrategy/excludedIPs/0` | `foobar` | -| `traefik/http/middlewares/Middleware12/ipAllowList/ipStrategy/excludedIPs/1` | `foobar` | -| `traefik/http/middlewares/Middleware12/ipAllowList/rejectStatusCode` | `404` | -| `traefik/http/middlewares/Middleware12/ipAllowList/sourceRange/0` | `foobar` | -| `traefik/http/middlewares/Middleware12/ipAllowList/sourceRange/1` | `foobar` | -| `traefik/http/middlewares/Middleware13/inFlightReq/amount` | `42` | -| `traefik/http/middlewares/Middleware13/inFlightReq/sourceCriterion/ipStrategy/depth` | `42` | -| `traefik/http/middlewares/Middleware13/inFlightReq/sourceCriterion/ipStrategy/excludedIPs/0` | `foobar` | -| `traefik/http/middlewares/Middleware13/inFlightReq/sourceCriterion/ipStrategy/excludedIPs/1` | `foobar` | -| `traefik/http/middlewares/Middleware13/inFlightReq/sourceCriterion/requestHeaderName` | `foobar` | -| `traefik/http/middlewares/Middleware13/inFlightReq/sourceCriterion/requestHost` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/issuer/commonName` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/issuer/country` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/issuer/domainComponent` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/issuer/locality` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/issuer/organization` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/issuer/province` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/issuer/serialNumber` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/notAfter` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/notBefore` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/sans` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/serialNumber` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/subject/commonName` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/subject/country` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/subject/domainComponent` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/subject/locality` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/subject/organization` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/subject/organizationalUnit` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/subject/province` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/info/subject/serialNumber` | `true` | -| `traefik/http/middlewares/Middleware14/passTLSClientCert/pem` | `true` | -| `traefik/http/middlewares/Middleware15/plugin/PluginConf/foo` | `bar` | -| `traefik/http/middlewares/Middleware16/rateLimit/average` | `42` | -| `traefik/http/middlewares/Middleware16/rateLimit/burst` | `42` | -| `traefik/http/middlewares/Middleware16/rateLimit/period` | `42s` | -| `traefik/http/middlewares/Middleware16/rateLimit/sourceCriterion/ipStrategy/depth` | `42` | -| `traefik/http/middlewares/Middleware16/rateLimit/sourceCriterion/ipStrategy/excludedIPs/0` | `foobar` | -| `traefik/http/middlewares/Middleware16/rateLimit/sourceCriterion/ipStrategy/excludedIPs/1` | `foobar` | -| `traefik/http/middlewares/Middleware16/rateLimit/sourceCriterion/requestHeaderName` | `foobar` | -| `traefik/http/middlewares/Middleware16/rateLimit/sourceCriterion/requestHost` | `true` | -| `traefik/http/middlewares/Middleware17/redirectRegex/permanent` | `true` | -| `traefik/http/middlewares/Middleware17/redirectRegex/regex` | `foobar` | -| `traefik/http/middlewares/Middleware17/redirectRegex/replacement` | `foobar` | -| `traefik/http/middlewares/Middleware18/redirectScheme/permanent` | `true` | -| `traefik/http/middlewares/Middleware18/redirectScheme/port` | `foobar` | -| `traefik/http/middlewares/Middleware18/redirectScheme/scheme` | `foobar` | -| `traefik/http/middlewares/Middleware19/replacePath/path` | `foobar` | -| `traefik/http/middlewares/Middleware20/replacePathRegex/regex` | `foobar` | -| `traefik/http/middlewares/Middleware20/replacePathRegex/replacement` | `foobar` | -| `traefik/http/middlewares/Middleware21/retry/attempts` | `42` | -| `traefik/http/middlewares/Middleware21/retry/initialInterval` | `42s` | -| `traefik/http/middlewares/Middleware22/stripPrefix/prefixes/0` | `foobar` | -| `traefik/http/middlewares/Middleware22/stripPrefix/prefixes/1` | `foobar` | -| `traefik/http/middlewares/Middleware23/stripPrefixRegex/regex/0` | `foobar` | -| `traefik/http/middlewares/Middleware23/stripPrefixRegex/regex/1` | `foobar` | -| `traefik/http/middlewares/Middleware24/grpcWeb/allowOrigins/0` | `foobar` | -| `traefik/http/middlewares/Middleware24/grpcWeb/allowOrigins/1` | `foobar` | + +| `traefik/http/middlewares/Middleware01/addPrefix/prefix` | `foobar` | +| `traefik/http/middlewares/Middleware02/basicAuth/headerField` | `foobar` | +| `traefik/http/middlewares/Middleware02/basicAuth/realm` | `foobar` | +| `traefik/http/middlewares/Middleware02/basicAuth/removeHeader` | `true` | +| `traefik/http/middlewares/Middleware02/basicAuth/users/0` | `foobar` | +| `traefik/http/middlewares/Middleware02/basicAuth/users/1` | `foobar` | +| `traefik/http/middlewares/Middleware02/basicAuth/usersFile` | `foobar` | +| `traefik/http/middlewares/Middleware03/buffering/maxRequestBodyBytes` | `42` | +| `traefik/http/middlewares/Middleware03/buffering/maxResponseBodyBytes` | `42` | +| `traefik/http/middlewares/Middleware03/buffering/memRequestBodyBytes` | `42` | +| `traefik/http/middlewares/Middleware03/buffering/memResponseBodyBytes` | `42` | +| `traefik/http/middlewares/Middleware03/buffering/retryExpression` | `foobar` | +| `traefik/http/middlewares/Middleware04/chain/middlewares/0` | `foobar` | +| `traefik/http/middlewares/Middleware04/chain/middlewares/1` | `foobar` | +| `traefik/http/middlewares/Middleware05/circuitBreaker/checkPeriod` | `42s` | +| `traefik/http/middlewares/Middleware05/circuitBreaker/expression` | `foobar` | +| `traefik/http/middlewares/Middleware05/circuitBreaker/fallbackDuration` | `42s` | +| `traefik/http/middlewares/Middleware05/circuitBreaker/recoveryDuration` | `42s` | +| `traefik/http/middlewares/Middleware06/compress/excludedContentTypes/0` | `foobar` | +| `traefik/http/middlewares/Middleware06/compress/excludedContentTypes/1` | `foobar` | +| `traefik/http/middlewares/Middleware06/compress/includedContentTypes/0` | `foobar` | +| `traefik/http/middlewares/Middleware06/compress/includedContentTypes/1` | `foobar` | +| `traefik/http/middlewares/Middleware06/compress/minResponseBodyBytes` | `42` | +| `traefik/http/middlewares/Middleware07/contentType` | `` | +| `traefik/http/middlewares/Middleware08/digestAuth/headerField` | `foobar` | +| `traefik/http/middlewares/Middleware08/digestAuth/realm` | `foobar` | +| `traefik/http/middlewares/Middleware08/digestAuth/removeHeader` | `true` | +| `traefik/http/middlewares/Middleware08/digestAuth/users/0` | `foobar` | +| `traefik/http/middlewares/Middleware08/digestAuth/users/1` | `foobar` | +| `traefik/http/middlewares/Middleware08/digestAuth/usersFile` | `foobar` | +| `traefik/http/middlewares/Middleware09/errors/query` | `foobar` | +| `traefik/http/middlewares/Middleware09/errors/service` | `foobar` | +| `traefik/http/middlewares/Middleware09/errors/status/0` | `foobar` | +| `traefik/http/middlewares/Middleware09/errors/status/1` | `foobar` | +| `traefik/http/middlewares/Middleware10/forwardAuth/addAuthCookiesToResponse/0` | `foobar` | +| `traefik/http/middlewares/Middleware10/forwardAuth/addAuthCookiesToResponse/1` | `foobar` | +| `traefik/http/middlewares/Middleware10/forwardAuth/address` | `foobar` | +| `traefik/http/middlewares/Middleware10/forwardAuth/authRequestHeaders/0` | `foobar` | +| `traefik/http/middlewares/Middleware10/forwardAuth/authRequestHeaders/1` | `foobar` | +| `traefik/http/middlewares/Middleware10/forwardAuth/authResponseHeaders/0` | `foobar` | +| `traefik/http/middlewares/Middleware10/forwardAuth/authResponseHeaders/1` | `foobar` | +| `traefik/http/middlewares/Middleware10/forwardAuth/authResponseHeadersRegex` | `foobar` | +| `traefik/http/middlewares/Middleware10/forwardAuth/tls/ca` | `foobar` | +| `traefik/http/middlewares/Middleware10/forwardAuth/tls/cert` | `foobar` | +| `traefik/http/middlewares/Middleware10/forwardAuth/tls/insecureSkipVerify` | `true` | +| `traefik/http/middlewares/Middleware10/forwardAuth/tls/key` | `foobar` | +| `traefik/http/middlewares/Middleware10/forwardAuth/trustForwardHeader` | `true` | +| `traefik/http/middlewares/Middleware11/grpcWeb/allowOrigins/0` | `foobar` | +| `traefik/http/middlewares/Middleware11/grpcWeb/allowOrigins/1` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/accessControlAllowCredentials` | `true` | +| `traefik/http/middlewares/Middleware12/headers/accessControlAllowHeaders/0` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/accessControlAllowHeaders/1` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/accessControlAllowMethods/0` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/accessControlAllowMethods/1` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/accessControlAllowOriginList/0` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/accessControlAllowOriginList/1` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/accessControlAllowOriginListRegex/0` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/accessControlAllowOriginListRegex/1` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/accessControlExposeHeaders/0` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/accessControlExposeHeaders/1` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/accessControlMaxAge` | `42` | +| `traefik/http/middlewares/Middleware12/headers/addVaryHeader` | `true` | +| `traefik/http/middlewares/Middleware12/headers/allowedHosts/0` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/allowedHosts/1` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/browserXssFilter` | `true` | +| `traefik/http/middlewares/Middleware12/headers/contentSecurityPolicy` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/contentTypeNosniff` | `true` | +| `traefik/http/middlewares/Middleware12/headers/customBrowserXSSValue` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/customFrameOptionsValue` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/customRequestHeaders/name0` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/customRequestHeaders/name1` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/customResponseHeaders/name0` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/customResponseHeaders/name1` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/forceSTSHeader` | `true` | +| `traefik/http/middlewares/Middleware12/headers/frameDeny` | `true` | +| `traefik/http/middlewares/Middleware12/headers/hostsProxyHeaders/0` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/hostsProxyHeaders/1` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/isDevelopment` | `true` | +| `traefik/http/middlewares/Middleware12/headers/permissionsPolicy` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/publicKey` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/referrerPolicy` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/sslProxyHeaders/name0` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/sslProxyHeaders/name1` | `foobar` | +| `traefik/http/middlewares/Middleware12/headers/stsIncludeSubdomains` | `true` | +| `traefik/http/middlewares/Middleware12/headers/stsPreload` | `true` | +| `traefik/http/middlewares/Middleware12/headers/stsSeconds` | `42` | +| `traefik/http/middlewares/Middleware13/ipAllowList/ipStrategy/depth` | `42` | +| `traefik/http/middlewares/Middleware13/ipAllowList/ipStrategy/excludedIPs/0` | `foobar` | +| `traefik/http/middlewares/Middleware13/ipAllowList/ipStrategy/excludedIPs/1` | `foobar` | +| `traefik/http/middlewares/Middleware13/ipAllowList/rejectStatusCode` | `42` | +| `traefik/http/middlewares/Middleware13/ipAllowList/sourceRange/0` | `foobar` | +| `traefik/http/middlewares/Middleware13/ipAllowList/sourceRange/1` | `foobar` | +| `traefik/http/middlewares/Middleware14/ipWhiteList/ipStrategy/depth` | `42` | +| `traefik/http/middlewares/Middleware14/ipWhiteList/ipStrategy/excludedIPs/0` | `foobar` | +| `traefik/http/middlewares/Middleware14/ipWhiteList/ipStrategy/excludedIPs/1` | `foobar` | +| `traefik/http/middlewares/Middleware14/ipWhiteList/sourceRange/0` | `foobar` | +| `traefik/http/middlewares/Middleware14/ipWhiteList/sourceRange/1` | `foobar` | +| `traefik/http/middlewares/Middleware15/inFlightReq/amount` | `42` | +| `traefik/http/middlewares/Middleware15/inFlightReq/sourceCriterion/ipStrategy/depth` | `42` | +| `traefik/http/middlewares/Middleware15/inFlightReq/sourceCriterion/ipStrategy/excludedIPs/0` | `foobar` | +| `traefik/http/middlewares/Middleware15/inFlightReq/sourceCriterion/ipStrategy/excludedIPs/1` | `foobar` | +| `traefik/http/middlewares/Middleware15/inFlightReq/sourceCriterion/requestHeaderName` | `foobar` | +| `traefik/http/middlewares/Middleware15/inFlightReq/sourceCriterion/requestHost` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/issuer/commonName` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/issuer/country` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/issuer/domainComponent` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/issuer/locality` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/issuer/organization` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/issuer/province` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/issuer/serialNumber` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/notAfter` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/notBefore` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/sans` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/serialNumber` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/subject/commonName` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/subject/country` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/subject/domainComponent` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/subject/locality` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/subject/organization` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/subject/organizationalUnit` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/subject/province` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/info/subject/serialNumber` | `true` | +| `traefik/http/middlewares/Middleware16/passTLSClientCert/pem` | `true` | +| `traefik/http/middlewares/Middleware17/plugin/PluginConf0/name0` | `foobar` | +| `traefik/http/middlewares/Middleware17/plugin/PluginConf0/name1` | `foobar` | +| `traefik/http/middlewares/Middleware17/plugin/PluginConf1/name0` | `foobar` | +| `traefik/http/middlewares/Middleware17/plugin/PluginConf1/name1` | `foobar` | +| `traefik/http/middlewares/Middleware18/rateLimit/average` | `42` | +| `traefik/http/middlewares/Middleware18/rateLimit/burst` | `42` | +| `traefik/http/middlewares/Middleware18/rateLimit/period` | `42s` | +| `traefik/http/middlewares/Middleware18/rateLimit/sourceCriterion/ipStrategy/depth` | `42` | +| `traefik/http/middlewares/Middleware18/rateLimit/sourceCriterion/ipStrategy/excludedIPs/0` | `foobar` | +| `traefik/http/middlewares/Middleware18/rateLimit/sourceCriterion/ipStrategy/excludedIPs/1` | `foobar` | +| `traefik/http/middlewares/Middleware18/rateLimit/sourceCriterion/requestHeaderName` | `foobar` | +| `traefik/http/middlewares/Middleware18/rateLimit/sourceCriterion/requestHost` | `true` | +| `traefik/http/middlewares/Middleware19/redirectRegex/permanent` | `true` | +| `traefik/http/middlewares/Middleware19/redirectRegex/regex` | `foobar` | +| `traefik/http/middlewares/Middleware19/redirectRegex/replacement` | `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/1` | `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/1` | `foobar` | | `traefik/http/serversTransports/ServersTransport1/spiffe/trustDomain` | `foobar` | -| `traefik/http/services/Service01/loadBalancer/healthCheck/followRedirects` | `true` | -| `traefik/http/services/Service01/loadBalancer/healthCheck/headers/name0` | `foobar` | -| `traefik/http/services/Service01/loadBalancer/healthCheck/headers/name1` | `foobar` | -| `traefik/http/services/Service01/loadBalancer/healthCheck/hostname` | `foobar` | -| `traefik/http/services/Service01/loadBalancer/healthCheck/interval` | `42s` | -| `traefik/http/services/Service01/loadBalancer/healthCheck/method` | `foobar` | -| `traefik/http/services/Service01/loadBalancer/healthCheck/mode` | `foobar` | -| `traefik/http/services/Service01/loadBalancer/healthCheck/path` | `foobar` | -| `traefik/http/services/Service01/loadBalancer/healthCheck/port` | `42` | -| `traefik/http/services/Service01/loadBalancer/healthCheck/scheme` | `foobar` | -| `traefik/http/services/Service01/loadBalancer/healthCheck/status` | `42` | -| `traefik/http/services/Service01/loadBalancer/healthCheck/timeout` | `42s` | -| `traefik/http/services/Service01/loadBalancer/passHostHeader` | `true` | -| `traefik/http/services/Service01/loadBalancer/responseForwarding/flushInterval` | `42s` | -| `traefik/http/services/Service01/loadBalancer/servers/0/url` | `foobar` | -| `traefik/http/services/Service01/loadBalancer/servers/1/url` | `foobar` | -| `traefik/http/services/Service01/loadBalancer/serversTransport` | `foobar` | -| `traefik/http/services/Service01/loadBalancer/sticky/cookie/httpOnly` | `true` | -| `traefik/http/services/Service01/loadBalancer/sticky/cookie/name` | `foobar` | -| `traefik/http/services/Service01/loadBalancer/sticky/cookie/sameSite` | `foobar` | -| `traefik/http/services/Service01/loadBalancer/sticky/cookie/secure` | `true` | -| `traefik/http/services/Service02/mirroring/healthCheck` | `` | -| `traefik/http/services/Service02/mirroring/maxBodySize` | `42` | -| `traefik/http/services/Service02/mirroring/mirrors/0/name` | `foobar` | -| `traefik/http/services/Service02/mirroring/mirrors/0/percent` | `42` | -| `traefik/http/services/Service02/mirroring/mirrors/1/name` | `foobar` | -| `traefik/http/services/Service02/mirroring/mirrors/1/percent` | `42` | -| `traefik/http/services/Service02/mirroring/service` | `foobar` | -| `traefik/http/services/Service03/weighted/healthCheck` | `` | -| `traefik/http/services/Service03/weighted/services/0/name` | `foobar` | -| `traefik/http/services/Service03/weighted/services/0/weight` | `42` | -| `traefik/http/services/Service03/weighted/services/1/name` | `foobar` | -| `traefik/http/services/Service03/weighted/services/1/weight` | `42` | -| `traefik/http/services/Service03/weighted/sticky/cookie/httpOnly` | `true` | -| `traefik/http/services/Service03/weighted/sticky/cookie/name` | `foobar` | -| `traefik/http/services/Service03/weighted/sticky/cookie/sameSite` | `foobar` | -| `traefik/http/services/Service03/weighted/sticky/cookie/secure` | `true` | -| `traefik/http/services/Service04/failover/fallback` | `foobar` | -| `traefik/http/services/Service04/failover/healthCheck` | `` | -| `traefik/http/services/Service04/failover/service` | `foobar` | -| `traefik/tcp/middlewares/TCPMiddleware00/ipAllowList/sourceRange/0` | `foobar` | -| `traefik/tcp/middlewares/TCPMiddleware00/ipAllowList/sourceRange/1` | `foobar` | -| `traefik/tcp/middlewares/TCPMiddleware01/inFlightConn/amount` | `42` | +| `traefik/http/services/Service01/failover/fallback` | `foobar` | +| `traefik/http/services/Service01/failover/healthCheck` | `` | +| `traefik/http/services/Service01/failover/service` | `foobar` | +| `traefik/http/services/Service02/loadBalancer/healthCheck/followRedirects` | `true` | +| `traefik/http/services/Service02/loadBalancer/healthCheck/headers/name0` | `foobar` | +| `traefik/http/services/Service02/loadBalancer/healthCheck/headers/name1` | `foobar` | +| `traefik/http/services/Service02/loadBalancer/healthCheck/hostname` | `foobar` | +| `traefik/http/services/Service02/loadBalancer/healthCheck/interval` | `42s` | +| `traefik/http/services/Service02/loadBalancer/healthCheck/method` | `foobar` | +| `traefik/http/services/Service02/loadBalancer/healthCheck/mode` | `foobar` | +| `traefik/http/services/Service02/loadBalancer/healthCheck/path` | `foobar` | +| `traefik/http/services/Service02/loadBalancer/healthCheck/port` | `42` | +| `traefik/http/services/Service02/loadBalancer/healthCheck/scheme` | `foobar` | +| `traefik/http/services/Service02/loadBalancer/healthCheck/status` | `42` | +| `traefik/http/services/Service02/loadBalancer/healthCheck/timeout` | `42s` | +| `traefik/http/services/Service02/loadBalancer/passHostHeader` | `true` | +| `traefik/http/services/Service02/loadBalancer/responseForwarding/flushInterval` | `42s` | +| `traefik/http/services/Service02/loadBalancer/servers/0/url` | `foobar` | +| `traefik/http/services/Service02/loadBalancer/servers/1/url` | `foobar` | +| `traefik/http/services/Service02/loadBalancer/serversTransport` | `foobar` | +| `traefik/http/services/Service02/loadBalancer/sticky/cookie/httpOnly` | `true` | +| `traefik/http/services/Service02/loadBalancer/sticky/cookie/maxAge` | `42` | +| `traefik/http/services/Service02/loadBalancer/sticky/cookie/name` | `foobar` | +| `traefik/http/services/Service02/loadBalancer/sticky/cookie/sameSite` | `foobar` | +| `traefik/http/services/Service02/loadBalancer/sticky/cookie/secure` | `true` | +| `traefik/http/services/Service03/mirroring/healthCheck` | `` | +| `traefik/http/services/Service03/mirroring/maxBodySize` | `42` | +| `traefik/http/services/Service03/mirroring/mirrors/0/name` | `foobar` | +| `traefik/http/services/Service03/mirroring/mirrors/0/percent` | `42` | +| `traefik/http/services/Service03/mirroring/mirrors/1/name` | `foobar` | +| `traefik/http/services/Service03/mirroring/mirrors/1/percent` | `42` | +| `traefik/http/services/Service03/mirroring/service` | `foobar` | +| `traefik/http/services/Service04/weighted/healthCheck` | `` | +| `traefik/http/services/Service04/weighted/services/0/name` | `foobar` | +| `traefik/http/services/Service04/weighted/services/0/weight` | `42` | +| `traefik/http/services/Service04/weighted/services/1/name` | `foobar` | +| `traefik/http/services/Service04/weighted/services/1/weight` | `42` | +| `traefik/http/services/Service04/weighted/sticky/cookie/httpOnly` | `true` | +| `traefik/http/services/Service04/weighted/sticky/cookie/maxAge` | `42` | +| `traefik/http/services/Service04/weighted/sticky/cookie/name` | `foobar` | +| `traefik/http/services/Service04/weighted/sticky/cookie/sameSite` | `foobar` | +| `traefik/http/services/Service04/weighted/sticky/cookie/secure` | `true` | +| `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/1` | `foobar` | | `traefik/tcp/routers/TCPRouter0/middlewares/0` | `foobar` | @@ -286,9 +301,6 @@ | `traefik/tcp/routers/TCPRouter1/tls/passthrough` | `true` | | `traefik/tcp/serversTransports/TCPServersTransport0/dialKeepAlive` | `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/tls/certificates/0/certFile` | `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/1` | `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/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/tls/certificates/0/certFile` | `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/1` | `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/servers/0/address` | `foobar` | | `traefik/tcp/services/TCPService01/loadBalancer/servers/0/tls` | `true` | diff --git a/docs/content/reference/dynamic-configuration/traefik.io_ingressroutes.yaml b/docs/content/reference/dynamic-configuration/traefik.io_ingressroutes.yaml index 94daf2095..41628b58a 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_ingressroutes.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_ingressroutes.yaml @@ -160,6 +160,12 @@ spec: can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string diff --git a/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml b/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml index 6eb4089c4..b7d8c6b52 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml @@ -175,6 +175,13 @@ spec: items: type: string 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: description: 'MinResponseBodyBytes defines the minimum amount of bytes a response body must have to be compressed. Default: @@ -295,6 +302,12 @@ spec: description: HTTPOnly defines whether the cookie can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string @@ -337,6 +350,12 @@ spec: This middleware delegates the request authentication to a Service. More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/forwardauth/' 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: description: Address defines the authentication server address. type: string diff --git a/docs/content/reference/dynamic-configuration/traefik.io_traefikservices.yaml b/docs/content/reference/dynamic-configuration/traefik.io_traefikservices.yaml index 9724e59b6..8620b4d74 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_traefikservices.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_traefikservices.yaml @@ -134,6 +134,12 @@ spec: description: HTTPOnly defines whether the cookie can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string @@ -225,6 +231,12 @@ spec: description: HTTPOnly defines whether the cookie can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string @@ -332,6 +344,12 @@ spec: description: HTTPOnly defines whether the cookie can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string @@ -371,6 +389,12 @@ spec: description: HTTPOnly defines whether the cookie can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index 58acc5ac7..3edf7ebc9 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -1,3 +1,5 @@ +## CODE GENERATED AUTOMATICALLY +## THIS FILE MUST NOT BE EDITED BY HAND [global] checkNewVersion = true sendAnonymousUsage = true @@ -6,26 +8,21 @@ insecureSkipVerify = true rootCAs = ["foobar", "foobar"] maxIdleConnsPerHost = 42 - [serversTransport.forwardingTimeouts] dialTimeout = "42s" responseHeaderTimeout = "42s" idleConnTimeout = "42s" - readIdleTimeout = "42s" - pingTimeout = "42s" - [serversTransport.spiffe] ids = ["foobar", "foobar"] trustDomain = "foobar" [tcpServersTransport] - dialTimeout = "42s" dialKeepAlive = "42s" - + dialTimeout = "42s" + terminationDelay = "42s" [tcpServersTransport.tls] insecureSkipVerify = true rootCAs = ["foobar", "foobar"] - [tcpServersTransport.tls.spiffe] ids = ["foobar", "foobar"] trustDomain = "foobar" @@ -35,8 +32,8 @@ address = "foobar" asDefault = true [entryPoints.EntryPoint0.transport] - keepAliveMaxRequests = 42 keepAliveMaxTime = "42s" + keepAliveMaxRequests = 42 [entryPoints.EntryPoint0.transport.lifeCycle] requestAcceptGraceTimeout = "42s" graceTimeOut = "42s" @@ -80,31 +77,31 @@ [providers] providersThrottleDuration = "42s" [providers.docker] - constraints = "foobar" - watch = true - endpoint = "foobar" - defaultRule = "foobar" exposedByDefault = true - useBindPortIP = true - network = "foobar" - httpClientTimeout = "42s" + constraints = "foobar" allowEmptyServices = true + network = "foobar" + useBindPortIP = true + watch = true + defaultRule = "foobar" + endpoint = "foobar" + httpClientTimeout = "42s" [providers.docker.tls] ca = "foobar" cert = "foobar" key = "foobar" insecureSkipVerify = true [providers.swarm] - constraints = "foobar" - watch = true - endpoint = "foobar" - defaultRule = "foobar" exposedByDefault = true - useBindPortIP = true - network = "foobar" - refreshSeconds = "42s" - httpClientTimeout = "42s" + constraints = "foobar" allowEmptyServices = true + network = "foobar" + useBindPortIP = true + watch = true + defaultRule = "foobar" + endpoint = "foobar" + httpClientTimeout = "42s" + refreshSeconds = "42s" [providers.swarm.tls] ca = "foobar" cert = "foobar" @@ -183,9 +180,9 @@ constraints = "foobar" prefix = "foobar" stale = true - namespaces = ["foobar", "foobar"] exposedByDefault = true refreshInterval = "42s" + namespaces = ["foobar", "foobar"] [providers.nomad.endpoint] address = "foobar" region = "foobar" @@ -203,11 +200,11 @@ defaultRule = "foobar" clusters = ["foobar", "foobar"] autoDiscoverClusters = true + healthyTasksOnly = true + ecsAnywhere = true region = "foobar" accessKeyID = "foobar" secretAccessKey = "foobar" - ecsAnywhere = true - healthyTasksOnly = true [providers.consul] rootKey = "foobar" endpoints = ["foobar", "foobar"] @@ -265,14 +262,18 @@ key = "foobar" insecureSkipVerify = true [providers.plugin] - [providers.plugin.Descriptor0] - [providers.plugin.Descriptor1] + [providers.plugin.PluginConf0] + name0 = "foobar" + name1 = "foobar" + [providers.plugin.PluginConf1] + name0 = "foobar" + name1 = "foobar" [api] insecure = true dashboard = true debug = true - disabledashboardad = false + disableDashboardAd = true [metrics] [metrics.prometheus] @@ -283,8 +284,8 @@ entryPoint = "foobar" manualRouting = true [metrics.prometheus.headerLabels] - label1 = "foobar" - label2 = "foobar" + name0 = "foobar" + name1 = "foobar" [metrics.datadog] address = "foobar" pushInterval = "42s" @@ -316,20 +317,19 @@ addEntryPointsLabels = true addRoutersLabels = true addServicesLabels = true - pushInterval = "42s" - path = "foobar" - explicitBoundaries = [42.0, 42.0] + explicitBoundaries = [42.0, 42.0] insecure = true + path = "foobar" + pushInterval = "42s" + [metrics.openTelemetry.grpc] [metrics.openTelemetry.headers] name0 = "foobar" name1 = "foobar" [metrics.openTelemetry.tls] ca = "foobar" - caOptional = true cert = "foobar" - insecureSkipVerify = true key = "foobar" - [metrics.openTelemetry.grpc] + insecureSkipVerify = true [ping] entryPoint = "foobar" @@ -342,8 +342,8 @@ noColor = true filePath = "foobar" maxSize = 42 - maxBackups = 42 maxAge = 42 + maxBackups = 42 compress = true [accessLog] @@ -367,28 +367,29 @@ [tracing] serviceName = "foobar" - sampleRate = 42 + sampleRate = 42.0 [tracing.headers] - header1 = "foobar" - header2 = "foobar" + name0 = "foobar" + name1 = "foobar" [tracing.globalAttributes] - attr1 = "foobar" - attr2 = "foobar" - [tracing.otlp.grpc] - endpoint = "foobar" - insecure = true - [tracing.otlp.grpc.tls] - ca = "foobar" - cert = "foobar" - key = "foobar" - insecureSkipVerify = true - [tracing.otlp.http] - endpoint = "foobar" - [tracing.otlp.http.tls] - ca = "foobar" - cert = "foobar" - key = "foobar" - insecureSkipVerify = true + name0 = "foobar" + name1 = "foobar" + [tracing.otlp] + [tracing.otlp.grpc] + endpoint = "foobar" + insecure = true + [tracing.otlp.grpc.tls] + ca = "foobar" + cert = "foobar" + key = "foobar" + insecureSkipVerify = true + [tracing.otlp.http] + endpoint = "foobar" + [tracing.otlp.http.tls] + ca = "foobar" + cert = "foobar" + key = "foobar" + insecureSkipVerify = true [hostResolver] cnameFlattening = true @@ -415,7 +416,27 @@ [certificatesResolvers.CertificateResolver0.acme.httpChallenge] entryPoint = "foobar" [certificatesResolvers.CertificateResolver0.acme.tlsChallenge] - [certificatesResolvers.CertificateResolver1.tailscale] + [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] [experimental] kubernetesGateway = true @@ -427,7 +448,10 @@ moduleName = "foobar" version = "foobar" [experimental.localPlugins] - [experimental.localPlugins.Descriptor0] + [experimental.localPlugins.LocalDescriptor0] moduleName = "foobar" - [experimental.localPlugins.Descriptor1] + [experimental.localPlugins.LocalDescriptor1] moduleName = "foobar" + +[spiffe] + workloadAPIAddr = "foobar" diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index d822979c9..a9ccffe9a 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -1,7 +1,9 @@ +## CODE GENERATED AUTOMATICALLY +## THIS FILE MUST NOT BE EDITED BY HAND global: checkNewVersion: true sendAnonymousUsage: true -serversTransports: +serversTransport: insecureSkipVerify: true rootCAs: - foobar @@ -11,16 +13,15 @@ serversTransports: dialTimeout: 42s responseHeaderTimeout: 42s idleConnTimeout: 42s - readIdleTimeout: 42s - pingTimeout: 42s spiffe: ids: - foobar - foobar trustDomain: foobar tcpServersTransport: - dialTimeout: 42s dialKeepAlive: 42s + dialTimeout: 42s + terminationDelay: 42s tls: insecureSkipVerify: true rootCAs: @@ -36,8 +37,6 @@ entryPoints: address: foobar asDefault: true transport: - keepAliveMaxRequests: 42 - keepAliveMaxTime: 42s lifeCycle: requestAcceptGraceTimeout: 42s graceTimeOut: 42s @@ -45,6 +44,8 @@ entryPoints: readTimeout: 42s writeTimeout: 42s idleTimeout: 42s + keepAliveMaxTime: 42s + keepAliveMaxRequests: 42 proxyProtocol: insecure: true trustedIPs: @@ -56,7 +57,6 @@ entryPoints: - foobar - foobar http: - encodeQuerySemicolons: true redirections: entryPoint: to: foobar @@ -78,6 +78,7 @@ entryPoints: sans: - foobar - foobar + encodeQuerySemicolons: true http2: maxConcurrentStreams: 42 http3: @@ -87,36 +88,36 @@ entryPoints: providers: providersThrottleDuration: 42s docker: + exposedByDefault: true constraints: foobar + allowEmptyServices: true + network: foobar + useBindPortIP: true watch: true - endpoint: foobar defaultRule: foobar + endpoint: foobar tls: ca: foobar cert: foobar key: foobar insecureSkipVerify: true - exposedByDefault: true - useBindPortIP: true - network: foobar httpClientTimeout: 42s - allowEmptyServices: true swarm: + exposedByDefault: true constraints: foobar + allowEmptyServices: true + network: foobar + useBindPortIP: true watch: true - endpoint: foobar defaultRule: foobar + endpoint: foobar tls: ca: foobar cert: foobar key: foobar insecureSkipVerify: true - exposedByDefault: true - useBindPortIP: true - network: foobar - refreshSeconds: 42s httpClientTimeout: 42s - allowEmptyServices: true + refreshSeconds: 42s file: directory: foobar watch: true @@ -131,14 +132,14 @@ providers: - foobar labelSelector: foobar ingressClass: foobar - throttleDuration: 42s - allowEmptyServices: true - allowExternalNameServices: true - disableIngressClassLookup: true ingressEndpoint: ip: foobar hostname: foobar publishedService: foobar + throttleDuration: 42s + allowEmptyServices: true + allowExternalNameServices: true + disableIngressClassLookup: true kubernetesCRD: endpoint: foobar token: foobar @@ -165,6 +166,20 @@ providers: insecure: true consulCatalog: 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 refreshInterval: 42s requireConsistent: true @@ -179,40 +194,26 @@ providers: namespaces: - 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: defaultRule: foobar constraints: foobar - prefix: foobar - stale: true - namespaces: - - foobar - - foobar - exposedByDefault: true - refreshInterval: 42s endpoint: address: foobar region: foobar token: foobar - endpointWaitTime: 42s tls: ca: foobar cert: foobar key: foobar insecureSkipVerify: true + endpointWaitTime: 42s + prefix: foobar + stale: true + exposedByDefault: true + refreshInterval: 42s + namespaces: + - foobar + - foobar ecs: constraints: foobar exposedByDefault: true @@ -222,37 +223,37 @@ providers: - foobar - foobar autoDiscoverClusters: true + healthyTasksOnly: true + ecsAnywhere: true region: foobar accessKeyID: foobar secretAccessKey: foobar - ecsAnywhere: true - healthyTasksOnly: true consul: rootKey: foobar endpoints: - foobar - foobar token: foobar - namespaces: - - foobar - - foobar tls: ca: foobar cert: foobar key: foobar insecureSkipVerify: true + namespaces: + - foobar + - foobar etcd: rootKey: foobar endpoints: - foobar - foobar - username: foobar - password: foobar tls: ca: foobar cert: foobar key: foobar insecureSkipVerify: true + username: foobar + password: foobar zooKeeper: rootKey: foobar endpoints: @@ -265,14 +266,14 @@ providers: endpoints: - foobar - foobar - username: foobar - password: foobar - db: 42 tls: ca: foobar cert: foobar key: foobar insecureSkipVerify: true + username: foobar + password: foobar + db: 42 sentinel: masterName: foobar username: foobar @@ -294,13 +295,17 @@ providers: key: foobar insecureSkipVerify: true plugin: - Descriptor0: {} - Descriptor1: {} + PluginConf0: + name0: foobar + name1: foobar + PluginConf1: + name0: foobar + name1: foobar api: insecure: true dashboard: true debug: true - disabledashboardad: false + disableDashboardAd: true metrics: prometheus: buckets: @@ -312,8 +317,8 @@ metrics: entryPoint: foobar manualRouting: true headerLabels: - label1: foobar - label2: foobar + name0: foobar + name1: foobar datadog: address: foobar pushInterval: 42s @@ -341,6 +346,7 @@ metrics: name0: foobar name1: foobar openTelemetry: + grpc: {} address: foobar addEntryPointsLabels: true addRoutersLabels: true @@ -356,12 +362,9 @@ metrics: pushInterval: 42s tls: ca: foobar - caOptional: true cert: foobar - insecureSkipVerify: true key: foobar - grpc: {} - + insecureSkipVerify: true ping: entryPoint: foobar manualRouting: true @@ -372,8 +375,8 @@ log: noColor: true filePath: foobar maxSize: 42 - maxBackups: 42 maxAge: 42 + maxBackups: 42 compress: true accessLog: filePath: foobar @@ -397,13 +400,13 @@ accessLog: bufferingSize: 42 tracing: serviceName: foobar - sampleRate: 42 headers: - header1: foobar - header2: foobar + name0: foobar + name1: foobar globalAttributes: - attr1: foobar - attr2: foobar + name0: foobar + name1: foobar + sampleRate: 42 otlp: grpc: endpoint: foobar @@ -429,13 +432,13 @@ certificatesResolvers: acme: email: foobar caServer: foobar - certificatesDuration: 42 preferredChain: foobar storage: foobar keyType: foobar eab: kid: foobar hmacEncoded: foobar + certificatesDuration: 42 dnsChallenge: provider: foobar delayBeforeCheck: 42s @@ -446,10 +449,30 @@ certificatesResolvers: httpChallenge: entryPoint: foobar tlsChallenge: {} + tailscale: {} 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: {} experimental: - kubernetesGateway: true plugins: Descriptor0: moduleName: foobar @@ -458,7 +481,10 @@ experimental: moduleName: foobar version: foobar localPlugins: - Descriptor0: + LocalDescriptor0: moduleName: foobar - Descriptor1: + LocalDescriptor1: moduleName: foobar + kubernetesGateway: true +spiffe: + workloadAPIAddr: foobar diff --git a/docs/content/routing/providers/consul-catalog.md b/docs/content/routing/providers/consul-catalog.md index 8eb985043..678e23b92 100644 --- a/docs/content/routing/providers/consul-catalog.md +++ b/docs/content/routing/providers/consul-catalog.md @@ -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 ``` +??? info "`traefik.http.services..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..loadbalancer.responseforwarding.flushinterval`" See [response forwarding](../services/index.md#response-forwarding) for more information. diff --git a/docs/content/routing/providers/docker.md b/docs/content/routing/providers/docker.md index 4a2b32436..0f6df9a9d 100644 --- a/docs/content/routing/providers/docker.md +++ b/docs/content/routing/providers/docker.md @@ -376,6 +376,14 @@ you'd add the label `traefik.http.services..loadbalancer.pa - "traefik.http.services.myservice.loadbalancer.sticky.cookie.samesite=none" ``` +??? info "`traefik.http.services..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..loadbalancer.responseforwarding.flushinterval`" See [response forwarding](../services/index.md#response-forwarding) for more information. diff --git a/docs/content/routing/providers/ecs.md b/docs/content/routing/providers/ecs.md index 718303c0b..e5c66a8c3 100644 --- a/docs/content/routing/providers/ecs.md +++ b/docs/content/routing/providers/ecs.md @@ -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 ``` +??? info "`traefik.http.services..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..loadbalancer.responseforwarding.flushinterval`" See [response forwarding](../services/index.md#response-forwarding) for more information. diff --git a/docs/content/routing/providers/kubernetes-crd.md b/docs/content/routing/providers/kubernetes-crd.md index c66cb3d52..55f25494a 100644 --- a/docs/content/routing/providers/kubernetes-crd.md +++ b/docs/content/routing/providers/kubernetes-crd.md @@ -348,6 +348,7 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne name: cookie secure: true sameSite: none + maxAge: 42 strategy: RoundRobin weight: 10 nativeLB: true # [11] diff --git a/docs/content/routing/providers/kubernetes-ingress.md b/docs/content/routing/providers/kubernetes-ingress.md index 5f9a32073..01f1d5166 100644 --- a/docs/content/routing/providers/kubernetes-ingress.md +++ b/docs/content/routing/providers/kubernetes-ingress.md @@ -351,6 +351,14 @@ which in turn will create the resulting routers, services, handlers, etc. 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+ If the Kubernetes cluster version is 1.18+, diff --git a/docs/content/routing/providers/kv.md b/docs/content/routing/providers/kv.md index a54ef1c61..3a6cc7744 100644 --- a/docs/content/routing/providers/kv.md +++ b/docs/content/routing/providers/kv.md @@ -244,6 +244,14 @@ A Story of key & values |-----------------------------------------------------------------------|--------| | `traefik/http/services/myservice/loadbalancer/sticky/cookie/samesite` | `none` | +??? info "`traefik/http/services//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//loadbalancer/responseforwarding/flushinterval`" See [response forwarding](../services/index.md#response-forwarding) for more information. @@ -306,6 +314,12 @@ A Story of key & values |------------------------------------------------------------------------|--------| | `traefik/http/services//weighted/sticky/cookie/httpOnly` | `true` | +??? info "`traefik/http/services//weighted/sticky/cookie/maxage`" + + | Key (Path) | Value | + |----------------------------------------------------------------------|-------| + | `traefik/http/services//weighted/sticky/cookie/maxage` | `42` | + ### Middleware More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md). diff --git a/docs/content/routing/providers/nomad.md b/docs/content/routing/providers/nomad.md index b0143d094..e1176c51d 100644 --- a/docs/content/routing/providers/nomad.md +++ b/docs/content/routing/providers/nomad.md @@ -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 ``` +??? info "`traefik.http.services..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..loadbalancer.responseforwarding.flushinterval`" See [response forwarding](../services/index.md#response-forwarding) for more information. diff --git a/docs/content/routing/services/index.md b/docs/content/routing/services/index.md index fb6af7563..7658195e1 100644 --- a/docs/content/routing/services/index.md +++ b/docs/content/routing/services/index.md @@ -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`). +!!! 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" By default, the affinity cookie is created without those flags. diff --git a/exp.Dockerfile b/exp.Dockerfile deleted file mode 100644 index 8098f9218..000000000 --- a/exp.Dockerfile +++ /dev/null @@ -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"] diff --git a/go.mod b/go.mod index f5a30e517..1e3228e15 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-retryablehttp v0.7.4 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/influxdata/influxdb-client-go/v2 v2.7.0 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/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // 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/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect diff --git a/go.sum b/go.sum index a44d026a4..9c0c8a0eb 100644 --- a/go.sum +++ b/go.sum @@ -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/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= 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/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= @@ -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.15.0 h1:2qK9nDrr4tiJKRoxPGhm6B7xJjLVIQqkjiab2M4aKjU= 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.1/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= +github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= +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.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= 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.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM= 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-20220506174431-b5665129cd1f/go.mod h1:b/AoT79m3PEpb6tKCFKva/M+q1rKJNUk5mdu1S8DymM= +github.com/hashicorp/nomad/api v0.0.0-20231213195942-64e3dca9274b h1:R1UDhkwGltpSPY9bCBBxIMQd+NY9BkN0vFHnJo/8o8w= +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.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= 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/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= 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 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/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= diff --git a/integration/fixtures/k8s/01-traefik-crd.yml b/integration/fixtures/k8s/01-traefik-crd.yml index e388639a9..5a4c63c3c 100644 --- a/integration/fixtures/k8s/01-traefik-crd.yml +++ b/integration/fixtures/k8s/01-traefik-crd.yml @@ -160,6 +160,12 @@ spec: can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string @@ -750,6 +756,13 @@ spec: items: type: string 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: description: 'MinResponseBodyBytes defines the minimum amount of bytes a response body must have to be compressed. Default: @@ -870,6 +883,12 @@ spec: description: HTTPOnly defines whether the cookie can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string @@ -912,6 +931,12 @@ spec: This middleware delegates the request authentication to a Service. More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/forwardauth/' 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: description: Address defines the authentication server address. type: string @@ -2145,6 +2170,12 @@ spec: description: HTTPOnly defines whether the cookie can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string @@ -2236,6 +2267,12 @@ spec: description: HTTPOnly defines whether the cookie can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string @@ -2343,6 +2380,12 @@ spec: description: HTTPOnly defines whether the cookie can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string @@ -2382,6 +2425,12 @@ spec: description: HTTPOnly defines whether the cookie can be accessed by client-side APIs, such as JavaScript. 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: description: Name defines the Cookie name. type: string diff --git a/integration/integration_test.go b/integration/integration_test.go index 703c4ac79..7149d8fd8 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -15,6 +15,7 @@ import ( "os/exec" "path/filepath" "regexp" + "runtime" "slices" "strings" "testing" @@ -56,8 +57,6 @@ type composeDeploy struct { Replicas int `yaml:"replicas"` } -var traefikBinary = "../dist/traefik" - type BaseSuite struct { suite.Suite containers map[string]testcontainers.Container @@ -308,7 +307,13 @@ func (s *BaseSuite) composeDown() { } 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.killCmd(cmd) diff --git a/internal/gendoc.go b/internal/gendoc.go index d4fad3247..93c03366e 100644 --- a/internal/gendoc.go +++ b/internal/gendoc.go @@ -1,10 +1,13 @@ package main import ( + "bytes" "fmt" "io" "os" "path" + "path/filepath" + "reflect" "sort" "strconv" "strings" @@ -16,9 +19,65 @@ import ( "github.com/traefik/paerser/generator" "github.com/traefik/paerser/parser" "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() { + 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) { return env.Encode(env.DefaultNamePrefix, i) }) @@ -26,6 +85,144 @@ func main() { 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)) { logger := log.With().Str("file", outputFile).Logger() @@ -117,6 +314,7 @@ func genKVDynConfDoc(outputFile string) { } store := storeWriter{data: map[string]string{}} + c := client{store: store} err = c.load("traefik", conf) if err != nil { @@ -130,6 +328,12 @@ func genKVDynConfDoc(outputFile string) { sort.Strings(keys) + _, _ = fmt.Fprintf(file, ` +`) + for _, k := range keys { _, _ = fmt.Fprintf(file, "| `%s` | `%s` |\n", k, store.data[k]) } diff --git a/internal/parser.go b/internal/parser.go new file mode 100644 index 000000000..3fa85617e --- /dev/null +++ b/internal/parser.go @@ -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) + } + } + } +} diff --git a/pkg/collector/collector_test.go b/pkg/collector/collector_test.go index 44c1ecef7..00034201a 100644 --- a/pkg/collector/collector_test.go +++ b/pkg/collector/collector_test.go @@ -5,13 +5,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/traefik/traefik/v3/pkg/collector/hydratation" "github.com/traefik/traefik/v3/pkg/config/static" ) func Test_createBody(t *testing.T) { var staticConfiguration static.Configuration - err := hydrate(&staticConfiguration) + err := hydratation.Hydrate(&staticConfiguration) require.NoError(t, err) buffer, err := createBody(&staticConfiguration) diff --git a/pkg/collector/hydration_test.go b/pkg/collector/hydratation/hydration.go similarity index 94% rename from pkg/collector/hydration_test.go rename to pkg/collector/hydratation/hydration.go index 8814888a6..a5ec52dee 100644 --- a/pkg/collector/hydration_test.go +++ b/pkg/collector/hydratation/hydration.go @@ -1,4 +1,4 @@ -package collector +package hydratation import ( "fmt" @@ -17,7 +17,8 @@ const ( defaultMapKeyPrefix = "name" ) -func hydrate(element interface{}) error { +// Hydrate hydrates a configuration. +func Hydrate(element interface{}) error { field := reflect.ValueOf(element) return fill(field) } @@ -41,9 +42,7 @@ func fill(field reflect.Value) error { return err } case reflect.Interface: - if err := fill(field.Elem()); err != nil { - return err - } + setTyped(field, defaultString) case reflect.String: setTyped(field, defaultString) case reflect.Int: @@ -118,7 +117,7 @@ func makeKeyName(typ reflect.Type) string { case reflect.String, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 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 default: return typ.Name() diff --git a/pkg/config/dynamic/config.go b/pkg/config/dynamic/config.go index af9f657af..621c004e8 100644 --- a/pkg/config/dynamic/config.go +++ b/pkg/config/dynamic/config.go @@ -24,7 +24,7 @@ type Configuration struct { 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"` 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 diff --git a/pkg/config/dynamic/http_config.go b/pkg/config/dynamic/http_config.go index 0c31c8871..a447e94eb 100644 --- a/pkg/config/dynamic/http_config.go +++ b/pkg/config/dynamic/http_config.go @@ -155,6 +155,10 @@ type Cookie struct { // SameSite defines the same site policy. // 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"` + // 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 diff --git a/pkg/config/dynamic/middlewares.go b/pkg/config/dynamic/middlewares.go index dcb884337..a2c1794eb 100644 --- a/pkg/config/dynamic/middlewares.go +++ b/pkg/config/dynamic/middlewares.go @@ -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. // `application/grpc` is always excluded. 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. // Default: 1024. 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. // If not set or empty then all request headers are passed. 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 diff --git a/pkg/config/dynamic/zz_generated.deepcopy.go b/pkg/config/dynamic/zz_generated.deepcopy.go index 62f468c11..43b80a5dc 100644 --- a/pkg/config/dynamic/zz_generated.deepcopy.go +++ b/pkg/config/dynamic/zz_generated.deepcopy.go @@ -132,6 +132,11 @@ func (in *Compress) DeepCopyInto(out *Compress) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.IncludedContentTypes != nil { + in, out := &in.IncludedContentTypes, &out.IncludedContentTypes + *out = make([]string, len(*in)) + copy(*out, *in) + } return } @@ -324,6 +329,11 @@ func (in *ForwardAuth) DeepCopyInto(out *ForwardAuth) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.AddAuthCookiesToResponse != nil { + in, out := &in.AddAuthCookiesToResponse, &out.AddAuthCookiesToResponse + *out = make([]string, len(*in)) + copy(*out, *in) + } return } diff --git a/pkg/config/label/label_test.go b/pkg/config/label/label_test.go index c55a73c15..28606cdbc 100644 --- a/pkg/config/label/label_test.go +++ b/pkg/config/label/label_test.go @@ -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.HTTPOnly": "true", "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.Service1.LoadBalancer.HealthCheck.Headers.name0": "foobar", "traefik.HTTP.Services.Service1.LoadBalancer.HealthCheck.Headers.name1": "foobar", diff --git a/pkg/middlewares/auth/forward.go b/pkg/middlewares/auth/forward.go index f93137469..6e3b3ac84 100644 --- a/pkg/middlewares/auth/forward.go +++ b/pkg/middlewares/auth/forward.go @@ -48,19 +48,26 @@ type forwardAuth struct { client http.Client trustForwardHeader bool authRequestHeaders []string + addAuthCookiesToResponse map[string]struct{} } // NewForward creates a forward auth middleware. 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") + addAuthCookiesToResponse := make(map[string]struct{}) + for _, cookieName := range config.AddAuthCookiesToResponse { + addAuthCookiesToResponse[cookieName] = struct{}{} + } + fa := &forwardAuth{ - address: config.Address, - authResponseHeaders: config.AuthResponseHeaders, - next: next, - name: name, - trustForwardHeader: config.TrustForwardHeader, - authRequestHeaders: config.AuthRequestHeaders, + address: config.Address, + authResponseHeaders: config.AuthResponseHeaders, + next: next, + name: name, + trustForwardHeader: config.TrustForwardHeader, + authRequestHeaders: config.AuthRequestHeaders, + addAuthCookiesToResponse: addAuthCookiesToResponse, } // 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) req.RequestURI = req.URL.RequestURI() - fa.next.ServeHTTP(rw, req) + + authCookies := forwardResponse.Cookies() + if len(authCookies) == 0 { + 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) { diff --git a/pkg/middlewares/auth/forward_test.go b/pkg/middlewares/auth/forward_test.go index e3afd6882..461d9b329 100644 --- a/pkg/middlewares/auth/forward_test.go +++ b/pkg/middlewares/auth/forward_test.go @@ -66,6 +66,8 @@ func TestForwardAuthSuccess(t *testing.T) { w.Header().Add("X-Auth-Group", "group1") w.Header().Add("X-Auth-Group", "group2") 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") })) 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, "auth-value", r.Header.Get("Foo-Bar")) 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") }) @@ -83,6 +88,7 @@ func TestForwardAuthSuccess(t *testing.T) { Address: server.URL, AuthResponseHeaders: []string{"X-Auth-User", "X-Auth-Group"}, AuthResponseHeadersRegex: "^Foo-", + AddAuthCookiesToResponse: []string{"authCookie"}, } middleware, err := NewForward(context.Background(), next, auth, "authTest") require.NoError(t, err) @@ -97,6 +103,8 @@ func TestForwardAuthSuccess(t *testing.T) { res, err := http.DefaultClient.Do(req) require.NoError(t, err) 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) require.NoError(t, err) diff --git a/pkg/middlewares/compress/brotli/brotli.go b/pkg/middlewares/compress/brotli/brotli.go index ebc93b5b3..c95a5ff66 100644 --- a/pkg/middlewares/compress/brotli/brotli.go +++ b/pkg/middlewares/compress/brotli/brotli.go @@ -22,7 +22,11 @@ const ( // Config is the Brotli handler configuration. type Config struct { // ExcludedContentTypes is the list of content types for which we should not compress. + // Mutually exclusive with the IncludedContentTypes option. 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 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") } - 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 { mediaType, params, err := mime.ParseMediaType(v) 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 { @@ -52,7 +70,8 @@ func NewWrapper(cfg Config) (func(http.Handler) http.HandlerFunc, error) { bw: brotli.NewWriter(rw), minSize: cfg.MinSize, statusCode: http.StatusOK, - excludedContentTypes: contentTypes, + excludedContentTypes: excludedContentTypes, + includedContentTypes: includedContentTypes, } defer brw.close() @@ -69,6 +88,7 @@ type responseWriter struct { minSize int excludedContentTypes []parsedContentType + includedContentTypes []parsedContentType buf []byte hijacked bool @@ -121,11 +141,25 @@ func (r *responseWriter) Write(p []byte) (int, error) { 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 != "" { mediaType, params, err := mime.ParseMediaType(ct) 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 { diff --git a/pkg/middlewares/compress/brotli/brotli_test.go b/pkg/middlewares/compress/brotli/brotli_test.go index ddbced0b7..5e1bfeea7 100644 --- a/pkg/middlewares/compress/brotli/brotli_test.go +++ b/pkg/middlewares/compress/brotli/brotli_test.go @@ -291,10 +291,9 @@ func Test_ExcludedContentTypes(t *testing.T) { expCompression bool }{ { - desc: "Always compress when content types are empty", - contentType: "", - excludedContentTypes: []string{}, - expCompression: true, + desc: "Always compress when content types are empty", + contentType: "", + expCompression: true, }, { desc: "MIME match", @@ -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) { testCases := []struct { desc string @@ -397,10 +501,9 @@ func Test_FlushExcludedContentTypes(t *testing.T) { expCompression bool }{ { - desc: "Always compress when content types are empty", - contentType: "", - excludedContentTypes: []string{}, - expCompression: true, + desc: "Always compress when content types are empty", + contentType: "", + expCompression: true, }, { desc: "MIME match", @@ -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 { t.Helper() diff --git a/pkg/middlewares/compress/compress.go b/pkg/middlewares/compress/compress.go index b7ae85b4d..0cdd29883 100644 --- a/pkg/middlewares/compress/compress.go +++ b/pkg/middlewares/compress/compress.go @@ -26,6 +26,7 @@ type compress struct { next http.Handler name string excludes []string + includes []string minSize int 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) { 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"} for _, v := range conf.ExcludedContentTypes { mediaType, _, err := mime.ParseMediaType(v) if err != nil { - return nil, err + return nil, fmt.Errorf("parsing excluded media type: %w", err) } 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 if conf.MinResponseBodyBytes > 0 { minSize = conf.MinResponseBodyBytes @@ -55,6 +70,7 @@ func New(ctx context.Context, next http.Handler, conf dynamic.Compress, name str next: next, name: name, excludes: excludes, + includes: includes, minSize: minSize, } @@ -92,11 +108,11 @@ func (c *compress) ServeHTTP(rw http.ResponseWriter, req *http.Request) { return } - // Client allows us to do whatever we want, so we br compress. - // See https://www.rfc-editor.org/rfc/rfc9110.html#section-12.5.3 + // Client doesn't specify a preferred encoding, for compatibility don't encode the request + // See https://github.com/traefik/traefik/issues/9734 acceptEncoding, ok := req.Header["Accept-Encoding"] if !ok { - c.brotliHandler.ServeHTTP(rw, req) + c.next.ServeHTTP(rw, req) return } @@ -118,10 +134,21 @@ func (c *compress) GetTracingInformation() (string, string, trace.SpanKind) { } func (c *compress) newGzipHandler() (http.Handler, error) { - wrapper, err := gzhttp.NewWrapper( - gzhttp.ExceptContentTypes(c.excludes), - gzhttp.MinSize(c.minSize), - ) + 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.MinSize(c.minSize), + ) + } + if err != nil { 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) { - cfg := brotli.Config{ - ExcludedContentTypes: c.excludes, - MinSize: c.minSize, + cfg := brotli.Config{MinSize: c.minSize} + if len(c.includes) > 0 { + cfg.IncludedContentTypes = c.includes + } else { + cfg.ExcludedContentTypes = c.excludes } wrapper, err := brotli.NewWrapper(cfg) diff --git a/pkg/middlewares/compress/compress_test.go b/pkg/middlewares/compress/compress_test.go index 23d6d765e..722001da3 100644 --- a/pkg/middlewares/compress/compress_test.go +++ b/pkg/middlewares/compress/compress_test.go @@ -10,7 +10,6 @@ import ( "net/textproto" "testing" - "github.com/andybalholm/brotli" "github.com/klauspost/compress/gzhttp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -35,7 +34,7 @@ func TestNegotiation(t *testing.T) { }{ { desc: "no accept header", - expEncoding: "br", + expEncoding: "", }, { desc: "unsupported accept header", @@ -151,7 +150,7 @@ func TestShouldNotCompressWhenContentEncodingHeader(t *testing.T) { 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) fakeBody := generateBytes(gzhttp.DefaultMinSize) @@ -167,12 +166,9 @@ func TestShouldCompressWhenNoAcceptEncodingHeader(t *testing.T) { rw := httptest.NewRecorder() handler.ServeHTTP(rw, req) - assert.Equal(t, brotliValue, rw.Header().Get(contentEncodingHeader)) - assert.Equal(t, acceptEncodingHeader, rw.Header().Get(varyHeader)) - - got, err := io.ReadAll(brotli.NewReader(rw.Body)) - require.NoError(t, err) - assert.Equal(t, got, fakeBody) + assert.Empty(t, rw.Header().Get(contentEncodingHeader)) + assert.Empty(t, rw.Header().Get(varyHeader)) + assert.EqualValues(t, rw.Body.Bytes(), fakeBody) } func TestShouldNotCompressWhenIdentityAcceptEncodingHeader(t *testing.T) { @@ -275,7 +271,28 @@ func TestShouldNotCompressWhenSpecificContentType(t *testing.T) { 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{}, 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) { fakeCompressedBody := generateBytes(100000) diff --git a/pkg/middlewares/headers/header.go b/pkg/middlewares/headers/header.go index 739358170..000cf4977 100644 --- a/pkg/middlewares/headers/header.go +++ b/pkg/middlewares/headers/header.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" "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 s.next != nil { - s.next.ServeHTTP(newResponseModifier(rw, req, s.PostRequestModifyResponseHeaders), req) + s.next.ServeHTTP(middlewares.NewResponseModifier(rw, req, s.PostRequestModifyResponseHeaders), req) } } diff --git a/pkg/middlewares/headers/secure.go b/pkg/middlewares/headers/secure.go index 99b03a489..1766e6356 100644 --- a/pkg/middlewares/headers/secure.go +++ b/pkg/middlewares/headers/secure.go @@ -4,6 +4,7 @@ import ( "net/http" "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/middlewares" "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) { 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) }) } diff --git a/pkg/middlewares/headers/responsewriter.go b/pkg/middlewares/response_modifier.go similarity index 76% rename from pkg/middlewares/headers/responsewriter.go rename to pkg/middlewares/response_modifier.go index 121389e59..77b76c740 100644 --- a/pkg/middlewares/headers/responsewriter.go +++ b/pkg/middlewares/response_modifier.go @@ -1,4 +1,4 @@ -package headers +package middlewares import ( "bufio" @@ -9,7 +9,8 @@ import ( "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 rw http.ResponseWriter @@ -21,9 +22,10 @@ type responseModifier struct { modifierErr error // returned by modifier call } -// modifier can be nil. -func newResponseModifier(w http.ResponseWriter, r *http.Request, modifier func(*http.Response) error) http.ResponseWriter { - return &responseModifier{ +// NewResponseModifier returns a new ResponseModifier instance. +// The given modifier can be nil. +func NewResponseModifier(w http.ResponseWriter, r *http.Request, modifier func(*http.Response) error) http.ResponseWriter { + return &ResponseModifier{ req: r, rw: w, 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, // allowing so further calls. -func (r *responseModifier) WriteHeader(code int) { +func (r *ResponseModifier) WriteHeader(code int) { if r.headersSent { return } @@ -73,11 +75,11 @@ func (r *responseModifier) WriteHeader(code int) { r.rw.WriteHeader(code) } -func (r *responseModifier) Header() http.Header { +func (r *ResponseModifier) Header() http.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) if r.modifierErr != nil { return 0, r.modifierErr @@ -87,7 +89,7 @@ func (r *responseModifier) Write(b []byte) (int, error) { } // 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 { return h.Hijack() } @@ -96,7 +98,7 @@ func (r *responseModifier) Hijack() (net.Conn, *bufio.ReadWriter, error) { } // Flush sends any buffered data to the client. -func (r *responseModifier) Flush() { +func (r *ResponseModifier) Flush() { if flusher, ok := r.rw.(http.Flusher); ok { flusher.Flush() } diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index 5023cf6c5..d5900aac5 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -731,6 +731,7 @@ func createForwardAuthMiddleware(k8sClient Client, namespace string, auth *traef AuthResponseHeaders: auth.AuthResponseHeaders, AuthResponseHeadersRegex: auth.AuthResponseHeadersRegex, AuthRequestHeaders: auth.AuthRequestHeaders, + AddAuthCookiesToResponse: auth.AddAuthCookiesToResponse, } if auth.TLS == nil { diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go index c86d51d3a..1378dc85d 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go @@ -157,6 +157,8 @@ type ForwardAuth struct { AuthRequestHeaders []string `json:"authRequestHeaders,omitempty"` // TLS defines the configuration used to secure the connection to the authentication server. 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. diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go index b08d2f7c4..40c9b979d 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go @@ -215,6 +215,11 @@ func (in *ForwardAuth) DeepCopyInto(out *ForwardAuth) { *out = new(ClientTLS) **out = **in } + if in.AddAuthCookiesToResponse != nil { + in, out := &in.AddAuthCookiesToResponse, &out.AddAuthCookiesToResponse + *out = make([]string, len(*in)) + copy(*out, *in) + } return } diff --git a/pkg/server/service/loadbalancer/wrr/wrr.go b/pkg/server/service/loadbalancer/wrr/wrr.go index 343c525d2..f38facf35 100644 --- a/pkg/server/service/loadbalancer/wrr/wrr.go +++ b/pkg/server/service/loadbalancer/wrr/wrr.go @@ -25,6 +25,7 @@ type stickyCookie struct { secure bool httpOnly bool sameSite string + maxAge int } func convertSameSite(sameSite string) http.SameSite { @@ -77,6 +78,7 @@ func New(sticky *dynamic.Sticky, wantHealthCheck bool) *Balancer { secure: sticky.Cookie.Secure, httpOnly: sticky.Cookie.HTTPOnly, 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, Secure: b.stickyCookie.secure, SameSite: convertSameSite(b.stickyCookie.sameSite), + MaxAge: b.stickyCookie.maxAge, } http.SetCookie(w, cookie) } diff --git a/pkg/server/service/loadbalancer/wrr/wrr_test.go b/pkg/server/service/loadbalancer/wrr/wrr_test.go index 2392ad84b..3708fa618 100644 --- a/pkg/server/service/loadbalancer/wrr/wrr_test.go +++ b/pkg/server/service/loadbalancer/wrr/wrr_test.go @@ -225,6 +225,7 @@ func TestSticky(t *testing.T) { Secure: true, HTTPOnly: true, SameSite: "none", + MaxAge: 42, }, }, false) @@ -261,6 +262,7 @@ func TestSticky(t *testing.T) { assert.True(t, recorder.cookies["test"].HttpOnly) assert.True(t, recorder.cookies["test"].Secure) assert.Equal(t, http.SameSiteNoneMode, recorder.cookies["test"].SameSite) + assert.Equal(t, 42, recorder.cookies["test"].MaxAge) } func TestSticky_FallBack(t *testing.T) { diff --git a/script/binary b/script/binary deleted file mode 100755 index c1de7c9bb..000000000 --- a/script/binary +++ /dev/null @@ -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 diff --git a/script/crossbinary-default b/script/crossbinary-default.sh similarity index 100% rename from script/crossbinary-default rename to script/crossbinary-default.sh diff --git a/script/generate b/script/generate deleted file mode 100755 index 423970b5a..000000000 --- a/script/generate +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -e - -go generate diff --git a/script/make.sh b/script/make.sh deleted file mode 100755 index 2f3870e74..000000000 --- a/script/make.sh +++ /dev/null @@ -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 diff --git a/script/release-packages.sh b/script/release-packages.sh new file mode 100755 index 000000000..f442e12dd --- /dev/null +++ b/script/release-packages.sh @@ -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/ diff --git a/script/test-integration b/script/test-integration deleted file mode 100755 index a6afba7d1..000000000 --- a/script/test-integration +++ /dev/null @@ -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[*]} diff --git a/script/test-unit b/script/test-unit deleted file mode 100755 index 7591307f4..000000000 --- a/script/test-unit +++ /dev/null @@ -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 diff --git a/script/validate-lint b/script/validate-lint deleted file mode 100755 index 937f7f13b..000000000 --- a/script/validate-lint +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -golangci-lint run diff --git a/script/validate-misspell b/script/validate-misspell.sh similarity index 100% rename from script/validate-misspell rename to script/validate-misspell.sh diff --git a/script/validate-vendor b/script/validate-vendor.sh similarity index 100% rename from script/validate-vendor rename to script/validate-vendor.sh