Merge branch 'master' of github.com:traefik/traefik
All checks were successful
Build & Push / build-and-push (push) Successful in 15m42s
All checks were successful
Build & Push / build-and-push (push) Successful in 15m42s
Signed-off-by: baalajimaestro <baalajimaestro@ptr.moe>
This commit is contained in:
commit
d9b8e79485
74 changed files with 1777 additions and 980 deletions
|
@ -162,8 +162,6 @@ linters-settings:
|
||||||
linters:
|
linters:
|
||||||
enable-all: true
|
enable-all: true
|
||||||
disable:
|
disable:
|
||||||
- execinquery # deprecated
|
|
||||||
- gomnd # deprecated
|
|
||||||
- sqlclosecheck # not relevant (SQL)
|
- sqlclosecheck # not relevant (SQL)
|
||||||
- rowserrcheck # not relevant (SQL)
|
- rowserrcheck # not relevant (SQL)
|
||||||
- cyclop # duplicate of gocyclo
|
- cyclop # duplicate of gocyclo
|
||||||
|
@ -286,4 +284,18 @@ issues:
|
||||||
- path: pkg/types/metrics.go
|
- path: pkg/types/metrics.go
|
||||||
linters:
|
linters:
|
||||||
- goconst
|
- goconst
|
||||||
|
- path: pkg/tls/certificate.go
|
||||||
|
text: 'the methods of "Certificates" use pointer receiver and non-pointer receiver.'
|
||||||
|
linters:
|
||||||
|
- recvcheck
|
||||||
|
- path: pkg/plugins/middlewarewasm.go
|
||||||
|
text: 'the methods of "wasmMiddlewareBuilder" use pointer receiver and non-pointer receiver.'
|
||||||
|
linters:
|
||||||
|
- recvcheck
|
||||||
|
|
||||||
|
output:
|
||||||
|
show-stats: true
|
||||||
|
sort-results: true
|
||||||
|
sort-order:
|
||||||
|
- linter
|
||||||
|
- file
|
||||||
|
|
|
@ -25,7 +25,7 @@ global_job_config:
|
||||||
- export "PATH=${GOPATH}/bin:${PATH}"
|
- export "PATH=${GOPATH}/bin:${PATH}"
|
||||||
- mkdir -vp "${SEMAPHORE_GIT_DIR}" "${GOPATH}/bin"
|
- mkdir -vp "${SEMAPHORE_GIT_DIR}" "${GOPATH}/bin"
|
||||||
- export GOPROXY=https://proxy.golang.org,direct
|
- export GOPROXY=https://proxy.golang.org,direct
|
||||||
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "${GOPATH}/bin" v1.61.0
|
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "${GOPATH}/bin" v1.62.0
|
||||||
- curl -sSfL https://gist.githubusercontent.com/traefiker/6d7ac019c11d011e4f131bb2cca8900e/raw/goreleaser.sh | bash -s -- -b "${GOPATH}/bin"
|
- curl -sSfL https://gist.githubusercontent.com/traefiker/6d7ac019c11d011e4f131bb2cca8900e/raw/goreleaser.sh | bash -s -- -b "${GOPATH}/bin"
|
||||||
- checkout
|
- checkout
|
||||||
- cache restore traefik-$(checksum go.sum)
|
- cache restore traefik-$(checksum go.sum)
|
||||||
|
|
39
CHANGELOG.md
39
CHANGELOG.md
|
@ -1,3 +1,42 @@
|
||||||
|
## [v3.2.1](https://github.com/traefik/traefik/tree/v3.2.1) (2024-11-20)
|
||||||
|
[All Commits](https://github.com/traefik/traefik/compare/v3.2.0...v3.2.1)
|
||||||
|
|
||||||
|
**Bug fixes:**
|
||||||
|
- **[k8s/ingress,k8s]** Fix HostRegexp config for rule syntax v2 ([#11288](https://github.com/traefik/traefik/pull/11288) by [kevinpollet](https://github.com/kevinpollet))
|
||||||
|
- **[logs]** Change level of peeking first byte error log to DEBUG for Postgres ([#11270](https://github.com/traefik/traefik/pull/11270) by [rtribotte](https://github.com/rtribotte))
|
||||||
|
- **[service,fastproxy]** Fix case problem for websocket upgrade ([#11246](https://github.com/traefik/traefik/pull/11246) by [juliens](https://github.com/juliens))
|
||||||
|
|
||||||
|
**Documentation:**
|
||||||
|
- **[acme,tls]** Document how to use Certificates of cert-manager ([#11053](https://github.com/traefik/traefik/pull/11053) by [mloiseleur](https://github.com/mloiseleur))
|
||||||
|
- **[docker/swarm]** Add tips about the use of docker in dynamic configuration for swarm provider ([#11207](https://github.com/traefik/traefik/pull/11207) by [webash](https://github.com/webash))
|
||||||
|
- **[middleware]** Add Compress middleware to migration guide ([#11229](https://github.com/traefik/traefik/pull/11229) by [logica0419](https://github.com/logica0419))
|
||||||
|
|
||||||
|
**Misc:**
|
||||||
|
- Merge branch v2.11 into v3.2 ([#11290](https://github.com/traefik/traefik/pull/11290) by [kevinpollet](https://github.com/kevinpollet))
|
||||||
|
- Merge branch v2.11 into v3.2 ([#11287](https://github.com/traefik/traefik/pull/11287) by [rtribotte](https://github.com/rtribotte))
|
||||||
|
- Merge branch v2.11 into v3.2 ([#11285](https://github.com/traefik/traefik/pull/11285) by [juliens](https://github.com/juliens))
|
||||||
|
- Merge branch v2.11 into v3.2 ([#11268](https://github.com/traefik/traefik/pull/11268) by [kevinpollet](https://github.com/kevinpollet))
|
||||||
|
|
||||||
|
## [v2.11.14](https://github.com/traefik/traefik/tree/v2.11.14) (2024-11-20)
|
||||||
|
[All Commits](https://github.com/traefik/traefik/compare/v2.11.13...v2.11.14)
|
||||||
|
|
||||||
|
**Bug fixes:**
|
||||||
|
- **[acme]** Update go-acme/lego to v4.20.2 ([#11263](https://github.com/traefik/traefik/pull/11263) by [ldez](https://github.com/ldez))
|
||||||
|
- **[logs,server]** Change level of peeking first byte error log to DEBUG ([#11254](https://github.com/traefik/traefik/pull/11254) by [rtribotte](https://github.com/rtribotte))
|
||||||
|
- **[middleware,server]** Drop untrusted X-Forwarded-Prefix header ([#11253](https://github.com/traefik/traefik/pull/11253) by [rtribotte](https://github.com/rtribotte))
|
||||||
|
- **[server]** Apply keepalive config to h2c entrypoints ([#11276](https://github.com/traefik/traefik/pull/11276) by [davefu113](https://github.com/davefu113))
|
||||||
|
- **[service]** Fix internal handlers ServiceBuilder composition ([#11281](https://github.com/traefik/traefik/pull/11281) by [juliens](https://github.com/juliens))
|
||||||
|
|
||||||
|
**Documentation:**
|
||||||
|
- **[accesslogs]** Update access-logs.md, add examples for accesslog.format ([#11275](https://github.com/traefik/traefik/pull/11275) by [bluepuma77](https://github.com/bluepuma77))
|
||||||
|
- Fix the defaultRule CLI examples ([#11282](https://github.com/traefik/traefik/pull/11282) by [kevinpollet](https://github.com/kevinpollet))
|
||||||
|
- Fix spelling, grammar, and rephrase sections for clarity in some documentation pages ([#11280](https://github.com/traefik/traefik/pull/11280) by [AntoineDeveloper](https://github.com/AntoineDeveloper))
|
||||||
|
- Fix absolute link in the migration guide ([#11269](https://github.com/traefik/traefik/pull/11269) by [kevinpollet](https://github.com/kevinpollet))
|
||||||
|
- Add X-Forwarded-Prefix to the migration guide ([#11267](https://github.com/traefik/traefik/pull/11267) by [kevinpollet](https://github.com/kevinpollet))
|
||||||
|
- Fix a small typo in entrypoints documentation ([#11261](https://github.com/traefik/traefik/pull/11261) by [quiode](https://github.com/quiode))
|
||||||
|
- Add a warning about environment variables casing for static configuration ([#11226](https://github.com/traefik/traefik/pull/11226) by [anchal00](https://github.com/anchal00))
|
||||||
|
- Improve documentation on dashboard ([#11220](https://github.com/traefik/traefik/pull/11220) by [mloiseleur](https://github.com/mloiseleur))
|
||||||
|
|
||||||
## [v3.2.0](https://github.com/traefik/traefik/tree/v3.2.0) (2024-10-28)
|
## [v3.2.0](https://github.com/traefik/traefik/tree/v3.2.0) (2024-10-28)
|
||||||
[All Commits](https://github.com/traefik/traefik/compare/v3.2.0-rc1...v3.2.0)
|
[All Commits](https://github.com/traefik/traefik/compare/v3.2.0-rc1...v3.2.0)
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ _(But if you'd rather configure some of your routes manually, Traefik supports t
|
||||||
- Provides HTTPS to your microservices by leveraging [Let's Encrypt](https://letsencrypt.org) (wildcard certificates support)
|
- Provides HTTPS to your microservices by leveraging [Let's Encrypt](https://letsencrypt.org) (wildcard certificates support)
|
||||||
- Circuit breakers, retry
|
- Circuit breakers, retry
|
||||||
- See the magic through its clean web UI
|
- See the magic through its clean web UI
|
||||||
- Websocket, HTTP/2, gRPC ready
|
- WebSocket, HTTP/2, gRPC ready
|
||||||
- Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB 2.X)
|
- Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB 2.X)
|
||||||
- Keeps access logs (JSON, CLF)
|
- Keeps access logs (JSON, CLF)
|
||||||
- Fast
|
- Fast
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Security Policy
|
# Security Policy
|
||||||
|
|
||||||
You can join our security mailing list to be aware of the latest announcements from our security team.
|
You can join our security mailing list to be aware of the latest announcements from our security team.
|
||||||
You can subscribe sending a mail to security+subscribe@traefik.io or on [the online viewer](https://groups.google.com/a/traefik.io/forum/#!forum/security).
|
You can subscribe by sending an email to security+subscribe@traefik.io or on [the online viewer](https://groups.google.com/a/traefik.io/forum/#!forum/security).
|
||||||
|
|
||||||
Reported vulnerabilities can be found on [cve.mitre.org](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=traefik).
|
Reported vulnerabilities can be found on [cve.mitre.org](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=traefik).
|
||||||
|
|
||||||
|
|
|
@ -189,11 +189,11 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
acmeProviders := initACMEProvider(staticConfiguration, &providerAggregator, tlsManager, httpChallengeProvider, tlsChallengeProvider)
|
acmeProviders := initACMEProvider(staticConfiguration, providerAggregator, tlsManager, httpChallengeProvider, tlsChallengeProvider)
|
||||||
|
|
||||||
// Tailscale
|
// Tailscale
|
||||||
|
|
||||||
tsProviders := initTailscaleProviders(staticConfiguration, &providerAggregator)
|
tsProviders := initTailscaleProviders(staticConfiguration, providerAggregator)
|
||||||
|
|
||||||
// Observability
|
// Observability
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ For development purposes, you can specify which tests to run by using (only work
|
||||||
|
|
||||||
Create `tailscale.secret` file in `integration` directory.
|
Create `tailscale.secret` file in `integration` directory.
|
||||||
|
|
||||||
This file need to contains a [Tailscale auth key](https://tailscale.com/kb/1085/auth-keys)
|
This file needs to contain a [Tailscale auth key](https://tailscale.com/kb/1085/auth-keys)
|
||||||
(an ephemeral, but reusable, one is recommended).
|
(an ephemeral, but reusable, one is recommended).
|
||||||
|
|
||||||
Add this section to your tailscale ACLs to auto-approve the routes for the
|
Add this section to your tailscale ACLs to auto-approve the routes for the
|
||||||
|
|
|
@ -15,13 +15,13 @@ Let's see how.
|
||||||
|
|
||||||
### General
|
### General
|
||||||
|
|
||||||
This [documentation](../../ "Link to the official Traefik documentation") is built with [MkDocs](https://mkdocs.org/ "Link to website of MkDocs").
|
This [documentation](../../ "Link to the official Traefik documentation") is built with [MkDocs](https://mkdocs.org/ "Link to the website of MkDocs").
|
||||||
|
|
||||||
### Method 1: `Docker` and `make`
|
### Method 1: `Docker` and `make`
|
||||||
|
|
||||||
Please make sure you have the following requirements installed:
|
Please make sure you have the following requirements installed:
|
||||||
|
|
||||||
- [Docker](https://www.docker.com/ "Link to website of Docker")
|
- [Docker](https://www.docker.com/ "Link to the website of Docker")
|
||||||
|
|
||||||
You can build the documentation and test it locally (with live reloading), using the `docs-serve` target:
|
You can build the documentation and test it locally (with live reloading), using the `docs-serve` target:
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ $ make docs-build
|
||||||
|
|
||||||
Please make sure you have the following requirements installed:
|
Please make sure you have the following requirements installed:
|
||||||
|
|
||||||
- [Python](https://www.python.org/ "Link to website of Python")
|
- [Python](https://www.python.org/ "Link to the website of Python")
|
||||||
- [pip](https://pypi.org/project/pip/ "Link to the website of pip on PyPI")
|
- [pip](https://pypi.org/project/pip/ "Link to the website of pip on PyPI")
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
@ -32,7 +32,7 @@ The contributor should also meet one or several of the following requirements:
|
||||||
including those of other maintainers and contributors.
|
including those of other maintainers and contributors.
|
||||||
|
|
||||||
- The contributor is active on Traefik Community forums
|
- The contributor is active on Traefik Community forums
|
||||||
or other technical forums/boards such as K8S slack, Reddit, StackOverflow, hacker news.
|
or other technical forums/boards, such as K8S Slack, Reddit, StackOverflow, and Hacker News.
|
||||||
|
|
||||||
Any existing active maintainer can create an issue to discuss promoting a contributor to maintainer.
|
Any existing active maintainer can create an issue to discuss promoting a contributor to maintainer.
|
||||||
Other maintainers can vote on the issue, and if the quorum is reached, the contributor is promoted to maintainer.
|
Other maintainers can vote on the issue, and if the quorum is reached, the contributor is promoted to maintainer.
|
||||||
|
|
|
@ -17,7 +17,7 @@ or the list of [confirmed bugs](https://github.com/traefik/traefik/labels/kind%2
|
||||||
|
|
||||||
## How We Prioritize
|
## How We Prioritize
|
||||||
|
|
||||||
We wish we could review every pull request right away, but because it's a time consuming operation, it's not always possible.
|
We wish we could review every pull request right away, but because it's a time-consuming operation, it's not always possible.
|
||||||
|
|
||||||
The PRs we are able to handle the fastest are:
|
The PRs we are able to handle the fastest are:
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ This label can be used when:
|
||||||
Traefik Proxy is made by the community for the community,
|
Traefik Proxy is made by the community for the community,
|
||||||
as such the goal is to engage the community to make Traefik the best reverse proxy available.
|
as such the goal is to engage the community to make Traefik the best reverse proxy available.
|
||||||
Part of this goal is maintaining a lean codebase and ensuring code velocity.
|
Part of this goal is maintaining a lean codebase and ensuring code velocity.
|
||||||
unfortunately, this means that sometimes we will not be able to merge a pull request.
|
Unfortunately, this means that sometimes we will not be able to merge a pull request.
|
||||||
|
|
||||||
Because we respect the work you did, you will always be told why we are closing your pull request.
|
Because we respect the work you did, you will always be told why we are closing your pull request.
|
||||||
If you do not agree with our decision, do not worry; closed pull requests are effortless to recreate,
|
If you do not agree with our decision, do not worry; closed pull requests are effortless to recreate,
|
||||||
|
|
|
@ -8,7 +8,7 @@ description: "Security is a key part of Traefik Proxy. Read the technical docume
|
||||||
## Security Advisories
|
## Security Advisories
|
||||||
|
|
||||||
We strongly advise you to join our mailing list to be aware of the latest announcements from our security team.
|
We strongly advise you to join our mailing list to be aware of the latest announcements from our security team.
|
||||||
You can subscribe sending a mail to security+subscribe@traefik.io or on [the online viewer](https://groups.google.com/a/traefik.io/forum/#!forum/security).
|
You can subscribe by sending an email to security+subscribe@traefik.io or on [the online viewer](https://groups.google.com/a/traefik.io/forum/#!forum/security).
|
||||||
|
|
||||||
## CVE
|
## CVE
|
||||||
|
|
||||||
|
|
|
@ -326,7 +326,7 @@ For complete details, refer to your provider's _Additional configuration_ link.
|
||||||
| [AzureDNS](https://azure.microsoft.com/services/dns/) | `azuredns` | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_TENANT_ID`, `AZURE_SUBSCRIPTION_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_ENVIRONMENT]`, `[AZURE_PRIVATE_ZONE]`, `[AZURE_ZONE_NAME]` | [Additional configuration](https://go-acme.github.io/lego/dns/azuredns) |
|
| [AzureDNS](https://azure.microsoft.com/services/dns/) | `azuredns` | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_TENANT_ID`, `AZURE_SUBSCRIPTION_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_ENVIRONMENT]`, `[AZURE_PRIVATE_ZONE]`, `[AZURE_ZONE_NAME]` | [Additional configuration](https://go-acme.github.io/lego/dns/azuredns) |
|
||||||
| [Bindman](https://github.com/labbsr0x/bindman-dns-webhook) | `bindman` | `BINDMAN_MANAGER_ADDRESS` | [Additional configuration](https://go-acme.github.io/lego/dns/bindman) |
|
| [Bindman](https://github.com/labbsr0x/bindman-dns-webhook) | `bindman` | `BINDMAN_MANAGER_ADDRESS` | [Additional configuration](https://go-acme.github.io/lego/dns/bindman) |
|
||||||
| [Blue Cat](https://www.bluecatnetworks.com/) | `bluecat` | `BLUECAT_SERVER_URL`, `BLUECAT_USER_NAME`, `BLUECAT_PASSWORD`, `BLUECAT_CONFIG_NAME`, `BLUECAT_DNS_VIEW` | [Additional configuration](https://go-acme.github.io/lego/dns/bluecat) |
|
| [Blue Cat](https://www.bluecatnetworks.com/) | `bluecat` | `BLUECAT_SERVER_URL`, `BLUECAT_USER_NAME`, `BLUECAT_PASSWORD`, `BLUECAT_CONFIG_NAME`, `BLUECAT_DNS_VIEW` | [Additional configuration](https://go-acme.github.io/lego/dns/bluecat) |
|
||||||
| [Brandit](https://www.brandit.com) | `brandit` | `BRANDIT_API_USERNAME`, `BRANDIT_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/brandit) |
|
| [Brandit](https://www.brandit.com) (DEPRECATED) | `brandit` | `BRANDIT_API_USERNAME`, `BRANDIT_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/brandit) |
|
||||||
| [Bunny](https://bunny.net) | `bunny` | `BUNNY_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/bunny) |
|
| [Bunny](https://bunny.net) | `bunny` | `BUNNY_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/bunny) |
|
||||||
| [Checkdomain](https://www.checkdomain.de/) | `checkdomain` | `CHECKDOMAIN_TOKEN`, | [Additional configuration](https://go-acme.github.io/lego/dns/checkdomain/) |
|
| [Checkdomain](https://www.checkdomain.de/) | `checkdomain` | `CHECKDOMAIN_TOKEN`, | [Additional configuration](https://go-acme.github.io/lego/dns/checkdomain/) |
|
||||||
| [Civo](https://www.civo.com/) | `civo` | `CIVO_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/civo) |
|
| [Civo](https://www.civo.com/) | `civo` | `CIVO_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/civo) |
|
||||||
|
@ -334,9 +334,10 @@ For complete details, refer to your provider's _Additional configuration_ link.
|
||||||
| [CloudDNS](https://vshosting.eu/) | `clouddns` | `CLOUDDNS_CLIENT_ID`, `CLOUDDNS_EMAIL`, `CLOUDDNS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/clouddns) |
|
| [CloudDNS](https://vshosting.eu/) | `clouddns` | `CLOUDDNS_CLIENT_ID`, `CLOUDDNS_EMAIL`, `CLOUDDNS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/clouddns) |
|
||||||
| [Cloudflare](https://www.cloudflare.com) | `cloudflare` | `CF_API_EMAIL`, `CF_API_KEY` [^5] or `CF_DNS_API_TOKEN`, `[CF_ZONE_API_TOKEN]` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudflare) |
|
| [Cloudflare](https://www.cloudflare.com) | `cloudflare` | `CF_API_EMAIL`, `CF_API_KEY` [^5] or `CF_DNS_API_TOKEN`, `[CF_ZONE_API_TOKEN]` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudflare) |
|
||||||
| [ClouDNS](https://www.cloudns.net/) | `cloudns` | `CLOUDNS_AUTH_ID`, `CLOUDNS_AUTH_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudns) |
|
| [ClouDNS](https://www.cloudns.net/) | `cloudns` | `CLOUDNS_AUTH_ID`, `CLOUDNS_AUTH_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudns) |
|
||||||
| [CloudXNS](https://www.cloudxns.net) | `cloudxns` | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudxns) |
|
| [CloudXNS](https://www.cloudxns.net) (DEPRECATED) | `cloudxns` | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudxns) |
|
||||||
| [ConoHa](https://www.conoha.jp) | `conoha` | `CONOHA_TENANT_ID`, `CONOHA_API_USERNAME`, `CONOHA_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/conoha) |
|
| [ConoHa](https://www.conoha.jp) | `conoha` | `CONOHA_TENANT_ID`, `CONOHA_API_USERNAME`, `CONOHA_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/conoha) |
|
||||||
| [Constellix](https://constellix.com) | `constellix` | `CONSTELLIX_API_KEY`, `CONSTELLIX_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/constellix) |
|
| [Constellix](https://constellix.com) | `constellix` | `CONSTELLIX_API_KEY`, `CONSTELLIX_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/constellix) |
|
||||||
|
| [Core-Networks](https://www.core-networks.de) | `corenetworks` | `CORENETWORKS_LOGIN`, `CORENETWORKS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/corenetworks) |
|
||||||
| [CPanel and WHM](https://cpanel.net/) | `cpanel` | `CPANEL_MODE`, `CPANEL_USERNAME`, `CPANEL_TOKEN`, `CPANEL_BASE_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/cpanel) |
|
| [CPanel and WHM](https://cpanel.net/) | `cpanel` | `CPANEL_MODE`, `CPANEL_USERNAME`, `CPANEL_TOKEN`, `CPANEL_BASE_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/cpanel) |
|
||||||
| [Derak Cloud](https://derak.cloud/) | `derak` | `DERAK_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/derak) |
|
| [Derak Cloud](https://derak.cloud/) | `derak` | `DERAK_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/derak) |
|
||||||
| [deSEC](https://desec.io) | `desec` | `DESEC_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/desec) |
|
| [deSEC](https://desec.io) | `desec` | `DESEC_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/desec) |
|
||||||
|
@ -418,6 +419,7 @@ For complete details, refer to your provider's _Additional configuration_ link.
|
||||||
| [Rackspace](https://www.rackspace.com/cloud/dns) | `rackspace` | `RACKSPACE_USER`, `RACKSPACE_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/rackspace) |
|
| [Rackspace](https://www.rackspace.com/cloud/dns) | `rackspace` | `RACKSPACE_USER`, `RACKSPACE_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/rackspace) |
|
||||||
| [RcodeZero](https://www.rcodezero.at) | `rcodezero` | `RCODEZERO_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/rcodezero) |
|
| [RcodeZero](https://www.rcodezero.at) | `rcodezero` | `RCODEZERO_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/rcodezero) |
|
||||||
| [reg.ru](https://www.reg.ru) | `regru` | `REGRU_USERNAME`, `REGRU_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/regru) |
|
| [reg.ru](https://www.reg.ru) | `regru` | `REGRU_USERNAME`, `REGRU_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/regru) |
|
||||||
|
| [Regfish](https://regfish.de) | `regfish` | `regfish` | [Additional configuration](https://go-acme.github.io/lego/dns/regfish) |
|
||||||
| [RFC2136](https://tools.ietf.org/html/rfc2136) | `rfc2136` | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER` | [Additional configuration](https://go-acme.github.io/lego/dns/rfc2136) |
|
| [RFC2136](https://tools.ietf.org/html/rfc2136) | `rfc2136` | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER` | [Additional configuration](https://go-acme.github.io/lego/dns/rfc2136) |
|
||||||
| [RimuHosting](https://rimuhosting.com) | `rimuhosting` | `RIMUHOSTING_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/rimuhosting) |
|
| [RimuHosting](https://rimuhosting.com) | `rimuhosting` | `RIMUHOSTING_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/rimuhosting) |
|
||||||
| [Route 53](https://aws.amazon.com/route53/) | `route53` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `[AWS_REGION]`, `[AWS_HOSTED_ZONE_ID]` or a configured user/instance IAM profile. | [Additional configuration](https://go-acme.github.io/lego/dns/route53) |
|
| [Route 53](https://aws.amazon.com/route53/) | `route53` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `[AWS_REGION]`, `[AWS_HOSTED_ZONE_ID]` or a configured user/instance IAM profile. | [Additional configuration](https://go-acme.github.io/lego/dns/route53) |
|
||||||
|
@ -431,7 +433,9 @@ For complete details, refer to your provider's _Additional configuration_ link.
|
||||||
| [Simply.com](https://www.simply.com/en/domains/) | `simply` | `SIMPLY_ACCOUNT_NAME`, `SIMPLY_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/simply) |
|
| [Simply.com](https://www.simply.com/en/domains/) | `simply` | `SIMPLY_ACCOUNT_NAME`, `SIMPLY_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/simply) |
|
||||||
| [Sonic](https://www.sonic.com/) | `sonic` | `SONIC_USER_ID`, `SONIC_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/sonic) |
|
| [Sonic](https://www.sonic.com/) | `sonic` | `SONIC_USER_ID`, `SONIC_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/sonic) |
|
||||||
| [Stackpath](https://www.stackpath.com/) | `stackpath` | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/stackpath) |
|
| [Stackpath](https://www.stackpath.com/) | `stackpath` | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/stackpath) |
|
||||||
|
| [Technitium](https://technitium.com) | `technitium` | `TECHNITIUM_SERVER_BASE_URL`, `TECHNITIUM_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/technitium) |
|
||||||
| [Tencent Cloud DNS](https://cloud.tencent.com/product/cns) | `tencentcloud` | `TENCENTCLOUD_SECRET_ID`, `TENCENTCLOUD_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/tencentcloud) |
|
| [Tencent Cloud DNS](https://cloud.tencent.com/product/cns) | `tencentcloud` | `TENCENTCLOUD_SECRET_ID`, `TENCENTCLOUD_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/tencentcloud) |
|
||||||
|
| [Timeweb Cloud](https://timeweb.cloud) | `timewebcloud` | `TIMEWEBCLOUD_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/timewebcloud) |
|
||||||
| [TransIP](https://www.transip.nl/) | `transip` | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/transip) |
|
| [TransIP](https://www.transip.nl/) | `transip` | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/transip) |
|
||||||
| [UKFast SafeDNS](https://docs.ukfast.co.uk/domains/safedns/index.html) | `safedns` | `SAFEDNS_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/safedns) |
|
| [UKFast SafeDNS](https://docs.ukfast.co.uk/domains/safedns/index.html) | `safedns` | `SAFEDNS_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/safedns) |
|
||||||
| [Ultradns](https://neustarsecurityservices.com/dns-services) | `ultradns` | `ULTRADNS_USERNAME`, `ULTRADNS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/ultradns) |
|
| [Ultradns](https://neustarsecurityservices.com/dns-services) | `ultradns` | `ULTRADNS_USERNAME`, `ULTRADNS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/ultradns) |
|
||||||
|
@ -441,6 +445,7 @@ For complete details, refer to your provider's _Additional configuration_ link.
|
||||||
| [Versio](https://www.versio.nl/domeinnamen) | `versio` | `VERSIO_USERNAME`, `VERSIO_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/versio) |
|
| [Versio](https://www.versio.nl/domeinnamen) | `versio` | `VERSIO_USERNAME`, `VERSIO_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/versio) |
|
||||||
| [VinylDNS](https://www.vinyldns.io) | `vinyldns` | `VINYLDNS_ACCESS_KEY`, `VINYLDNS_SECRET_KEY`, `VINYLDNS_HOST` | [Additional configuration](https://go-acme.github.io/lego/dns/vinyldns) |
|
| [VinylDNS](https://www.vinyldns.io) | `vinyldns` | `VINYLDNS_ACCESS_KEY`, `VINYLDNS_SECRET_KEY`, `VINYLDNS_HOST` | [Additional configuration](https://go-acme.github.io/lego/dns/vinyldns) |
|
||||||
| [VK Cloud](https://mcs.mail.ru/) | `vkcloud` | `VK_CLOUD_PASSWORD`, `VK_CLOUD_PROJECT_ID`, `VK_CLOUD_USERNAME` | [Additional configuration](https://go-acme.github.io/lego/dns/vkcloud) |
|
| [VK Cloud](https://mcs.mail.ru/) | `vkcloud` | `VK_CLOUD_PASSWORD`, `VK_CLOUD_PROJECT_ID`, `VK_CLOUD_USERNAME` | [Additional configuration](https://go-acme.github.io/lego/dns/vkcloud) |
|
||||||
|
| [Volcano Engine](https://www.volcengine.com) | `volcengine` | `VOLC_ACCESSKEY`, `VOLC_SECRETKEY` | [Additional configuration](https://go-acme.github.io/lego/dns/volcengine) |
|
||||||
| [Vscale](https://vscale.io/) | `vscale` | `VSCALE_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/vscale) |
|
| [Vscale](https://vscale.io/) | `vscale` | `VSCALE_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/vscale) |
|
||||||
| [VULTR](https://www.vultr.com) | `vultr` | `VULTR_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/vultr) |
|
| [VULTR](https://www.vultr.com) | `vultr` | `VULTR_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/vultr) |
|
||||||
| [Webnames](https://www.webnames.ru/) | `webnames` | `WEBNAMES_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/webnames) |
|
| [Webnames](https://www.webnames.ru/) | `webnames` | `WEBNAMES_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/webnames) |
|
||||||
|
|
|
@ -652,3 +652,10 @@ As a consequence, middlewares do not have access to those Connection headers,
|
||||||
and a new option has been introduced to specify which ones could go through the middleware chain before being removed: `<entrypoint>.forwardedHeaders.connection`.
|
and a new option has been introduced to specify which ones could go through the middleware chain before being removed: `<entrypoint>.forwardedHeaders.connection`.
|
||||||
|
|
||||||
Please check out the [entrypoint forwarded headers connection option configuration](../routing/entrypoints.md#forwarded-headers) documentation.
|
Please check out the [entrypoint forwarded headers connection option configuration](../routing/entrypoints.md#forwarded-headers) documentation.
|
||||||
|
|
||||||
|
## v2.11.14
|
||||||
|
|
||||||
|
### X-Forwarded-Prefix
|
||||||
|
|
||||||
|
In `v2.11.14`, the `X-Forwarded-Prefix` header is now handled like the other `X-Forwarded-*` headers: Traefik removes it when it's sent from an untrusted source.
|
||||||
|
Please refer to the Forwarded headers [documentation](../routing/entrypoints.md#forwarded-headers) for more details.
|
||||||
|
|
|
@ -80,7 +80,7 @@ Please use the `disableClusterScopeResources` option instead to avoid cluster sc
|
||||||
|
|
||||||
### Kubernetes CRD Provider
|
### Kubernetes CRD Provider
|
||||||
|
|
||||||
Starting with v3.2, the CRDs has been updated on [TraefikService](../routing/services#mirroring-service) (PR [#11032](https://github.com/traefik/traefik/pull/11032)) and on [RateLimit](../middlewares/http/ratelimit) & [InFlightReq](../middlewares/http/inflightreq) middlewares (PR [#9747](https://github.com/traefik/traefik/pull/9747)).
|
Starting with v3.2, the CRDs has been updated on [TraefikService](../routing/services#mirroring-service) (PR [#11032](https://github.com/traefik/traefik/pull/11032)), on [RateLimit](../middlewares/http/ratelimit) & [InFlightReq](../middlewares/http/inflightreq) middlewares (PR [#9747](https://github.com/traefik/traefik/pull/9747)) and on [Compress](../middlewares/http/compress) middleware (PR [#10943](https://github.com/traefik/traefik/pull/10943)).
|
||||||
|
|
||||||
This update adds only new optional fields.
|
This update adds only new optional fields.
|
||||||
CRDs can be updated with this command:
|
CRDs can be updated with this command:
|
||||||
|
@ -153,3 +153,10 @@ the `configmaps`, `backendtlspolicies` and `backendtlspolicies/status` rights ha
|
||||||
- update
|
- update
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## v3.2.1
|
||||||
|
|
||||||
|
### X-Forwarded-Prefix
|
||||||
|
|
||||||
|
In `v3.2.1`, the `X-Forwarded-Prefix` header is now handled like the other `X-Forwarded-*` headers: Traefik removes it when it's sent from an untrusted source.
|
||||||
|
Please refer to the Forwarded headers [documentation](../routing/entrypoints.md#forwarded-headers) for more details.
|
||||||
|
|
|
@ -79,6 +79,20 @@ If the given format is unsupported, the default (CLF) is used instead.
|
||||||
<remote_IP_address> - <client_user_name_if_available> [<timestamp>] "<request_method> <request_path> <request_protocol>" <HTTP_status> <content-length> "<request_referrer>" "<request_user_agent>" <number_of_requests_received_since_Traefik_started> "<Traefik_router_name>" "<Traefik_server_URL>" <request_duration_in_ms>ms
|
<remote_IP_address> - <client_user_name_if_available> [<timestamp>] "<request_method> <request_path> <request_protocol>" <HTTP_status> <content-length> "<request_referrer>" "<request_user_agent>" <number_of_requests_received_since_Traefik_started> "<Traefik_router_name>" "<Traefik_server_URL>" <request_duration_in_ms>ms
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```yaml tab="File (YAML)"
|
||||||
|
accessLog:
|
||||||
|
format: "json"
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml tab="File (TOML)"
|
||||||
|
[accessLog]
|
||||||
|
format = "json"
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="CLI"
|
||||||
|
--accesslog.format=json
|
||||||
|
```
|
||||||
|
|
||||||
### `bufferingSize`
|
### `bufferingSize`
|
||||||
|
|
||||||
To write the logs in an asynchronous fashion, specify a `bufferingSize` option.
|
To write the logs in an asynchronous fashion, specify a `bufferingSize` option.
|
||||||
|
|
|
@ -70,7 +70,7 @@ And then define a routing configuration on Traefik itself with the
|
||||||
|
|
||||||
### `insecure`
|
### `insecure`
|
||||||
|
|
||||||
Enable the API in `insecure` mode, which means that the API will be available directly on the entryPoint named `traefik`.
|
Enable the API in `insecure` mode, which means that the API will be available directly on the entryPoint named `traefik`, on path `/api`.
|
||||||
|
|
||||||
!!! info
|
!!! info
|
||||||
If the entryPoint named `traefik` is not configured, it will be automatically created on port 8080.
|
If the entryPoint named `traefik` is not configured, it will be automatically created on port 8080.
|
||||||
|
|
|
@ -37,32 +37,15 @@ Start by enabling the dashboard by using the following option from [Traefik's AP
|
||||||
on the [static configuration](../getting-started/configuration-overview.md#the-static-configuration):
|
on the [static configuration](../getting-started/configuration-overview.md#the-static-configuration):
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
api:
|
api: {}
|
||||||
# Dashboard
|
|
||||||
#
|
|
||||||
# Optional
|
|
||||||
# Default: true
|
|
||||||
#
|
|
||||||
dashboard: true
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
[api]
|
[api]
|
||||||
# Dashboard
|
|
||||||
#
|
|
||||||
# Optional
|
|
||||||
# Default: true
|
|
||||||
#
|
|
||||||
dashboard = true
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
# Dashboard
|
--api=true
|
||||||
#
|
|
||||||
# Optional
|
|
||||||
# Default: true
|
|
||||||
#
|
|
||||||
--api.dashboard=true
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Then define a routing configuration on Traefik itself,
|
Then define a routing configuration on Traefik itself,
|
||||||
|
@ -106,27 +89,47 @@ rule = "Host(`traefik.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashb
|
||||||
|
|
||||||
## Insecure Mode
|
## Insecure Mode
|
||||||
|
|
||||||
This mode is not recommended because it does not allow the use of security features.
|
When _insecure_ mode is enabled, one can access the dashboard on the `traefik` port (default: `8080`) of the Traefik instance,
|
||||||
|
at the following URL: `http://<Traefik IP>:8080/dashboard/` (trailing slash is mandatory).
|
||||||
|
|
||||||
To enable the "insecure mode", use the following options from [Traefik's API](./api.md#insecure):
|
This mode is **not** recommended because it does not allow security features.
|
||||||
|
For example, it is not possible to add an authentication middleware with this mode.
|
||||||
|
|
||||||
|
It should be used for testing purpose **only**.
|
||||||
|
|
||||||
|
To enable the _insecure_ mode, use the following options from [Traefik's API](./api.md#insecure):
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
api:
|
api:
|
||||||
dashboard: true
|
|
||||||
insecure: true
|
insecure: true
|
||||||
```
|
```
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
[api]
|
[api]
|
||||||
dashboard = true
|
|
||||||
insecure = true
|
insecure = true
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
--api.dashboard=true --api.insecure=true
|
--api.insecure=true
|
||||||
```
|
```
|
||||||
|
|
||||||
You can now access the dashboard on the port `8080` of the Traefik instance,
|
## Disable The Dashboard
|
||||||
at the following URL: `http://<Traefik IP>:8080/dashboard/` (trailing slash is mandatory).
|
|
||||||
|
By default, the dashboard is enabled when the API is enabled.
|
||||||
|
If necessary, the dashboard can be disabled by using the following option.
|
||||||
|
|
||||||
|
```yaml tab="File (YAML)"
|
||||||
|
api:
|
||||||
|
dashboard: false
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml tab="File (TOML)"
|
||||||
|
[api]
|
||||||
|
dashboard = false
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash tab="CLI"
|
||||||
|
--api.dashboard=false
|
||||||
|
```
|
||||||
|
|
||||||
{!traefik-for-business-applications.md!}
|
{!traefik-for-business-applications.md!}
|
||||||
|
|
|
@ -525,7 +525,7 @@ providers:
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
--providers.consulcatalog.defaultRule=Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)
|
--providers.consulcatalog.defaultRule='Host(`{{ .Name }}.{{ index .Labels "customLabel"}}`)'
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -455,7 +455,7 @@ providers:
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
--providers.docker.defaultRule=Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)
|
--providers.docker.defaultRule='Host(`{{ .Name }}.{{ index .Labels "customLabel"}}`)'
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -283,7 +283,7 @@ providers:
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
--providers.ecs.defaultRule=Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)
|
--providers.ecs.defaultRule='Host(`{{ .Name }}.{{ index .Labels "customLabel"}}`)'
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -432,7 +432,7 @@ providers:
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
--providers.nomad.defaultRule="Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
|
--providers.nomad.defaultRule='Host(`{{ .Name }}.{{ index .Labels "customLabel"}}`)'
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -455,7 +455,10 @@ _Optional, Default=""_
|
||||||
|
|
||||||
Defines a default docker network to use for connections to all containers.
|
Defines a default docker network to use for connections to all containers.
|
||||||
|
|
||||||
This option can be overridden on a per-container basis with the `traefik.docker.network` label.
|
This option can be overridden on a per-container basis with the `traefik.docker.network` [routing label](../routing/providers/swarm.md#traefikdockernetwork).
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
The Docker Swarm provider still uses the same per-container mechanism as the Docker provider, so therefore the label still uses the `docker` keyword intentionally.
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
providers:
|
providers:
|
||||||
|
@ -500,7 +503,7 @@ providers:
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash tab="CLI"
|
```bash tab="CLI"
|
||||||
--providers.swarm.defaultRule=Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)
|
--providers.swarm.defaultRule='Host(`{{ .Name }}.{{ index .Labels "customLabel"}}`)'
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -5,4 +5,23 @@ description: "Reference the environment variables for static configuration in Tr
|
||||||
|
|
||||||
# Static Configuration: Environment variables
|
# Static Configuration: Environment variables
|
||||||
|
|
||||||
|
!!! warning "Environment Variable Casing"
|
||||||
|
|
||||||
|
Traefik normalizes the environment variable key-value pairs by lowercasing them.
|
||||||
|
This means that when you interpolate a string in an environment variable's name,
|
||||||
|
that string will be treated as lowercase, regardless of its original casing.
|
||||||
|
|
||||||
|
For example, assuming you have set environment variables as follows:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export TRAEFIK_ENTRYPOINTS_WEB=true
|
||||||
|
export TRAEFIK_ENTRYPOINTS_WEB_ADDRESS=:80
|
||||||
|
|
||||||
|
export TRAEFIK_CERTIFICATESRESOLVERS_myResolver=true
|
||||||
|
export TRAEFIK_CERTIFICATESRESOLVERS_myResolver_ACME_CASERVER=....
|
||||||
|
```
|
||||||
|
|
||||||
|
Although the Entrypoint is named `WEB` and the Certificate Resolver is named `myResolver`,
|
||||||
|
they have to be referenced respectively as `web`, and `myresolver` in the configuration.
|
||||||
|
|
||||||
--8<-- "content/reference/static-configuration/env-ref.md"
|
--8<-- "content/reference/static-configuration/env-ref.md"
|
||||||
|
|
|
@ -579,7 +579,7 @@ Setting them has no effect for UDP entryPoints.
|
||||||
If zero, no timeout exists.
|
If zero, no timeout exists.
|
||||||
Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).
|
Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits).
|
||||||
If no units are provided, the value is parsed assuming seconds.
|
If no units are provided, the value is parsed assuming seconds.
|
||||||
We strongly suggest to adapt this value accordingly to the your needs.
|
We strongly suggest adapting this value accordingly to your needs.
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
## Static configuration
|
## Static configuration
|
||||||
|
|
|
@ -667,6 +667,9 @@ Overrides the default docker network to use for connections to the container.
|
||||||
If a container is linked to several networks, be sure to set the proper network name (you can check this with `docker inspect <container_id>`),
|
If a container is linked to several networks, be sure to set the proper network name (you can check this with `docker inspect <container_id>`),
|
||||||
otherwise it will randomly pick one (depending on how docker is returning them).
|
otherwise it will randomly pick one (depending on how docker is returning them).
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
The Docker Swarm provider still uses the same per-container mechanism as the Docker provider, so therefore the label still uses the `docker` keyword intentionally.
|
||||||
|
|
||||||
!!! warning
|
!!! warning
|
||||||
When deploying a stack from a compose file `stack`, the networks defined are prefixed with `stack`.
|
When deploying a stack from a compose file `stack`, the networks defined are prefixed with `stack`.
|
||||||
|
|
||||||
|
@ -680,3 +683,6 @@ Enables Swarm's inbuilt load balancer (only relevant in Swarm Mode).
|
||||||
|
|
||||||
If you enable this option, Traefik will use the virtual IP provided by docker swarm instead of the containers IPs.
|
If you enable this option, Traefik will use the virtual IP provided by docker swarm instead of the containers IPs.
|
||||||
Which means that Traefik will not perform any kind of load balancing and will delegate this task to swarm.
|
Which means that Traefik will not perform any kind of load balancing and will delegate this task to swarm.
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
The Docker Swarm provider still uses the same per-container mechanism as the Docker provider, so therefore the label still uses the `docker` keyword intentionally.
|
||||||
|
|
183
docs/content/user-guides/cert-manager.md
Normal file
183
docs/content/user-guides/cert-manager.md
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
---
|
||||||
|
title: "Integration with cert-manager"
|
||||||
|
description: "Learn how to use cert-manager certificates with Traefik Proxy for your routers. Read the technical documentation."
|
||||||
|
---
|
||||||
|
|
||||||
|
# cert-manager
|
||||||
|
|
||||||
|
Provision TLS Certificate for Traefik Proxy with cert-manager on Kubernetes
|
||||||
|
{: .subtitle }
|
||||||
|
|
||||||
|
## Pre-requisites
|
||||||
|
|
||||||
|
To obtain certificates from cert-manager that can be used in Traefik Proxy, you will need to:
|
||||||
|
|
||||||
|
1. Have cert-manager properly configured
|
||||||
|
2. Have Traefik Proxy configured
|
||||||
|
|
||||||
|
The certificates can then be used in an Ingress / IngressRoute / HTTPRoute.
|
||||||
|
|
||||||
|
## Example with ACME and HTTP challenge
|
||||||
|
|
||||||
|
!!! example "ACME issuer for HTTP challenge"
|
||||||
|
|
||||||
|
```yaml tab="Issuer"
|
||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: Issuer
|
||||||
|
metadata:
|
||||||
|
name: acme
|
||||||
|
|
||||||
|
spec:
|
||||||
|
acme:
|
||||||
|
# Production server is on https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
# Use staging by default.
|
||||||
|
server: https://acme-staging-v02.api.letsencrypt.org/directory
|
||||||
|
privateKeySecretRef:
|
||||||
|
name: acme
|
||||||
|
solvers:
|
||||||
|
- http01:
|
||||||
|
ingress:
|
||||||
|
ingressClassName: traefik
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Certificate"
|
||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: Certificate
|
||||||
|
metadata:
|
||||||
|
name: whoami
|
||||||
|
namespace: traefik
|
||||||
|
spec:
|
||||||
|
secretName: domain-tls # <=== Name of secret where the generated certificate will be stored.
|
||||||
|
dnsNames:
|
||||||
|
- "domain.example.com"
|
||||||
|
issuerRef:
|
||||||
|
name: acme
|
||||||
|
kind: Issuer
|
||||||
|
```
|
||||||
|
|
||||||
|
Let's see now how to use it with the various Kubernetes providers of Traefik Proxy.
|
||||||
|
The enabled providers can be seen on the [dashboard](../../operations/dashboard/) of Traefik Proxy and also in the INFO logs when Traefik Proxy starts.
|
||||||
|
|
||||||
|
### With an Ingress
|
||||||
|
|
||||||
|
To use this certificate with an Ingress, the [Kubernetes Ingress](../../providers/kubernetes-ingress/) provider has to be enabled.
|
||||||
|
|
||||||
|
!!! info Traefik Helm Chart
|
||||||
|
|
||||||
|
This provider is enabled by default in the Traefik Helm Chart.
|
||||||
|
|
||||||
|
!!! example "Route with this Certificate"
|
||||||
|
|
||||||
|
```yaml tab="Ingress"
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: domain
|
||||||
|
annotations:
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: domain.example.com
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Exact
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: domain-service
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
tls:
|
||||||
|
- secretName: domain-tls # <=== Use the name defined in Certificate resource.
|
||||||
|
```
|
||||||
|
|
||||||
|
### With an IngressRoute
|
||||||
|
|
||||||
|
To use this certificate with an IngressRoute, the [Kubernetes CRD](../../providers/kubernetes-crd) provider has to be enabled.
|
||||||
|
|
||||||
|
!!! info Traefik Helm Chart
|
||||||
|
|
||||||
|
This provider is enabled by default in the Traefik Helm Chart.
|
||||||
|
|
||||||
|
!!! example "Route with this Certificate"
|
||||||
|
|
||||||
|
```yaml tab="IngressRoute"
|
||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: IngressRoute
|
||||||
|
metadata:
|
||||||
|
name: domain
|
||||||
|
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- websecure
|
||||||
|
|
||||||
|
routes:
|
||||||
|
- match: Host(`domain.example.com`)
|
||||||
|
kind: Rule
|
||||||
|
services:
|
||||||
|
- name: domain-service
|
||||||
|
port: 80
|
||||||
|
tls:
|
||||||
|
secretName: domain-tls # <=== Use the name defined in Certificate resource.
|
||||||
|
```
|
||||||
|
|
||||||
|
### With an HTTPRoute
|
||||||
|
|
||||||
|
To use this certificate with an HTTPRoute, the [Kubernetes Gateway](../../routing/providers/kubernetes-gateway) provider has to be enabled.
|
||||||
|
|
||||||
|
!!! info Traefik Helm Chart
|
||||||
|
|
||||||
|
This provider is disabled by default in the Traefik Helm Chart.
|
||||||
|
|
||||||
|
!!! example "Route with this Certificate"
|
||||||
|
|
||||||
|
```yaml tab="HTTPRoute"
|
||||||
|
---
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: Gateway
|
||||||
|
metadata:
|
||||||
|
name: domain-gateway
|
||||||
|
spec:
|
||||||
|
gatewayClassName: traefik
|
||||||
|
listeners:
|
||||||
|
- name: websecure
|
||||||
|
port: 8443
|
||||||
|
protocol: HTTPS
|
||||||
|
hostname: domain.example.com
|
||||||
|
tls:
|
||||||
|
certificateRefs:
|
||||||
|
- name: domain-tls # <==== Use the name defined in Certificate resource.
|
||||||
|
---
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: HTTPRoute
|
||||||
|
metadata:
|
||||||
|
name: domain
|
||||||
|
spec:
|
||||||
|
parentRefs:
|
||||||
|
- name: domain-gateway
|
||||||
|
hostnames:
|
||||||
|
- domain.example.com
|
||||||
|
rules:
|
||||||
|
- matches:
|
||||||
|
- path:
|
||||||
|
type: Exact
|
||||||
|
value: /
|
||||||
|
|
||||||
|
backendRefs:
|
||||||
|
- name: domain-service
|
||||||
|
port: 80
|
||||||
|
weight: 1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
There are multiple event sources available to investigate when using cert-manager:
|
||||||
|
|
||||||
|
1. Kubernetes events in `Certificate` and `CertificateRequest` resources
|
||||||
|
2. cert-manager logs
|
||||||
|
3. Dashboard and/or (debug) logs from Traefik Proxy
|
||||||
|
|
||||||
|
cert-manager documentation provides a [detailed guide](https://cert-manager.io/docs/troubleshooting/) on how to troubleshoot a certificate request.
|
||||||
|
|
||||||
|
{!traefik-for-business-applications.md!}
|
|
@ -165,6 +165,7 @@ nav:
|
||||||
- 'User Guides':
|
- 'User Guides':
|
||||||
- 'FastProxy': 'user-guides/fastproxy.md'
|
- 'FastProxy': 'user-guides/fastproxy.md'
|
||||||
- 'Kubernetes and Let''s Encrypt': 'user-guides/crd-acme/index.md'
|
- 'Kubernetes and Let''s Encrypt': 'user-guides/crd-acme/index.md'
|
||||||
|
- 'Kubernetes and cert-manager': 'user-guides/cert-manager.md'
|
||||||
- 'gRPC Examples': 'user-guides/grpc.md'
|
- 'gRPC Examples': 'user-guides/grpc.md'
|
||||||
- 'Docker':
|
- 'Docker':
|
||||||
- 'Basic Example': 'user-guides/docker-compose/basic-example/index.md'
|
- 'Basic Example': 'user-guides/docker-compose/basic-example/index.md'
|
||||||
|
|
106
go.mod
106
go.mod
|
@ -18,7 +18,7 @@ require (
|
||||||
github.com/docker/go-connections v0.5.0
|
github.com/docker/go-connections v0.5.0
|
||||||
github.com/fatih/structs v1.1.0
|
github.com/fatih/structs v1.1.0
|
||||||
github.com/fsnotify/fsnotify v1.7.0
|
github.com/fsnotify/fsnotify v1.7.0
|
||||||
github.com/go-acme/lego/v4 v4.19.2
|
github.com/go-acme/lego/v4 v4.20.2
|
||||||
github.com/go-kit/kit v0.13.0
|
github.com/go-kit/kit v0.13.0
|
||||||
github.com/go-kit/log v0.2.1
|
github.com/go-kit/log v0.2.1
|
||||||
github.com/golang/protobuf v1.5.4
|
github.com/golang/protobuf v1.5.4
|
||||||
|
@ -29,8 +29,8 @@ require (
|
||||||
github.com/hashicorp/go-hclog v1.6.3
|
github.com/hashicorp/go-hclog v1.6.3
|
||||||
github.com/hashicorp/go-multierror v1.1.1
|
github.com/hashicorp/go-multierror v1.1.1
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.7
|
github.com/hashicorp/go-retryablehttp v0.7.7
|
||||||
github.com/hashicorp/go-version v1.6.0
|
github.com/hashicorp/go-version v1.7.0
|
||||||
github.com/hashicorp/nomad/api v0.0.0-20240122103822-8a4bd61caf74 // No tag on the repo.
|
github.com/hashicorp/nomad/api v0.0.0-20231213195942-64e3dca9274b // No tag on the repo.
|
||||||
github.com/http-wasm/http-wasm-host-go v0.7.0
|
github.com/http-wasm/http-wasm-host-go v0.7.0
|
||||||
github.com/influxdata/influxdb-client-go/v2 v2.7.0
|
github.com/influxdata/influxdb-client-go/v2 v2.7.0
|
||||||
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab // No tag on the repo.
|
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab // No tag on the repo.
|
||||||
|
@ -85,13 +85,13 @@ require (
|
||||||
go.opentelemetry.io/otel/trace v1.29.0
|
go.opentelemetry.io/otel/trace v1.29.0
|
||||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // No tag on the repo.
|
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // No tag on the repo.
|
||||||
golang.org/x/mod v0.21.0
|
golang.org/x/mod v0.21.0
|
||||||
golang.org/x/net v0.29.0
|
golang.org/x/net v0.30.0
|
||||||
golang.org/x/sync v0.8.0
|
golang.org/x/sync v0.8.0
|
||||||
golang.org/x/sys v0.25.0
|
golang.org/x/sys v0.26.0
|
||||||
golang.org/x/text v0.18.0
|
golang.org/x/text v0.19.0
|
||||||
golang.org/x/time v0.6.0
|
golang.org/x/time v0.7.0
|
||||||
golang.org/x/tools v0.25.0
|
golang.org/x/tools v0.25.0
|
||||||
google.golang.org/grpc v1.66.2
|
google.golang.org/grpc v1.67.1
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
k8s.io/api v0.31.1
|
k8s.io/api v0.31.1
|
||||||
|
@ -106,17 +106,17 @@ require (
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/auth v0.9.3 // indirect
|
cloud.google.com/go/auth v0.10.0 // indirect
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
|
cloud.google.com/go/auth/oauth2adapt v0.2.5 // indirect
|
||||||
cloud.google.com/go/compute/metadata v0.5.1 // indirect
|
cloud.google.com/go/compute/metadata v0.5.2 // indirect
|
||||||
dario.cat/mergo v1.0.0 // indirect
|
dario.cat/mergo v1.0.0 // indirect
|
||||||
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
|
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
|
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.2.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 // indirect
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||||
|
@ -137,30 +137,30 @@ require (
|
||||||
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
|
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
|
||||||
github.com/VividCortex/gohistogram v1.0.0 // indirect
|
github.com/VividCortex/gohistogram v1.0.0 // indirect
|
||||||
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 // indirect
|
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 // indirect
|
||||||
github.com/aliyun/alibaba-cloud-sdk-go v1.63.15 // indirect
|
github.com/aliyun/alibaba-cloud-sdk-go v1.63.47 // indirect
|
||||||
github.com/armon/go-metrics v0.4.1 // indirect
|
github.com/armon/go-metrics v0.4.1 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2 v1.30.5 // indirect
|
github.com/aws/aws-sdk-go-v2 v1.32.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.27.33 // indirect
|
github.com/aws/aws-sdk-go-v2/config v1.28.1 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.32 // indirect
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.42 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13 // indirect
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.18 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.40.6 // indirect
|
github.com/aws/aws-sdk-go-v2/service/lightsail v1.42.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.43.2 // indirect
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.46.0 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.7 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sso v1.24.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7 // indirect
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.7 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sts v1.32.3 // indirect
|
||||||
github.com/aws/smithy-go v1.20.4 // indirect
|
github.com/aws/smithy-go v1.22.0 // indirect
|
||||||
github.com/benbjohnson/clock v1.3.0 // indirect
|
github.com/benbjohnson/clock v1.3.0 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||||
github.com/bytedance/sonic v1.10.0 // indirect
|
github.com/bytedance/sonic v1.10.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/civo/civogo v0.3.11 // indirect
|
github.com/civo/civogo v0.3.11 // indirect
|
||||||
github.com/cloudflare/cloudflare-go v0.104.0 // indirect
|
github.com/cloudflare/cloudflare-go v0.108.0 // indirect
|
||||||
github.com/containerd/containerd v1.7.20 // indirect
|
github.com/containerd/containerd v1.7.20 // indirect
|
||||||
github.com/containerd/log v0.1.0 // indirect
|
github.com/containerd/log v0.1.0 // indirect
|
||||||
github.com/containerd/platforms v0.2.1 // indirect
|
github.com/containerd/platforms v0.2.1 // indirect
|
||||||
|
@ -177,7 +177,7 @@ require (
|
||||||
github.com/docker/go-units v0.5.0 // indirect
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
github.com/emicklei/go-restful/v3 v3.12.0 // indirect
|
github.com/emicklei/go-restful/v3 v3.12.0 // indirect
|
||||||
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
|
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
|
||||||
github.com/exoscale/egoscale/v3 v3.1.5 // indirect
|
github.com/exoscale/egoscale/v3 v3.1.7 // indirect
|
||||||
github.com/fatih/color v1.17.0 // indirect
|
github.com/fatih/color v1.17.0 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||||
|
@ -199,12 +199,12 @@ require (
|
||||||
github.com/go-playground/validator/v10 v10.16.0 // indirect
|
github.com/go-playground/validator/v10 v10.16.0 // indirect
|
||||||
github.com/go-resty/resty/v2 v2.13.1 // indirect
|
github.com/go-resty/resty/v2 v2.13.1 // indirect
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||||
github.com/go-viper/mapstructure/v2 v2.1.0 // indirect
|
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||||
github.com/go-zookeeper/zk v1.0.3 // indirect
|
github.com/go-zookeeper/zk v1.0.3 // indirect
|
||||||
github.com/goccy/go-json v0.10.3 // indirect
|
github.com/goccy/go-json v0.10.3 // indirect
|
||||||
github.com/gofrs/flock v0.12.1 // indirect
|
github.com/gofrs/flock v0.12.1 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/google/gnostic-models v0.6.8 // indirect
|
github.com/google/gnostic-models v0.6.8 // indirect
|
||||||
|
@ -216,7 +216,7 @@ require (
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
|
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
|
||||||
github.com/gophercloud/gophercloud v1.14.0 // indirect
|
github.com/gophercloud/gophercloud v1.14.1 // indirect
|
||||||
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 // indirect
|
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 // indirect
|
||||||
github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect
|
github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
|
||||||
|
@ -230,7 +230,7 @@ require (
|
||||||
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
|
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
|
||||||
github.com/hashicorp/serf v0.10.1 // indirect
|
github.com/hashicorp/serf v0.10.1 // indirect
|
||||||
github.com/huandu/xstrings v1.5.0 // indirect
|
github.com/huandu/xstrings v1.5.0 // indirect
|
||||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.114 // indirect
|
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.120 // indirect
|
||||||
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
|
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
|
||||||
github.com/imdario/mergo v0.3.16 // indirect
|
github.com/imdario/mergo v0.3.16 // indirect
|
||||||
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect
|
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect
|
||||||
|
@ -246,7 +246,7 @@ require (
|
||||||
github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect
|
github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect
|
||||||
github.com/labbsr0x/goh v1.0.1 // indirect
|
github.com/labbsr0x/goh v1.0.1 // indirect
|
||||||
github.com/leodido/go-urn v1.2.4 // indirect
|
github.com/leodido/go-urn v1.2.4 // indirect
|
||||||
github.com/linode/linodego v1.40.0 // indirect
|
github.com/linode/linodego v1.42.0 // indirect
|
||||||
github.com/liquidweb/liquidweb-cli v0.6.9 // indirect
|
github.com/liquidweb/liquidweb-cli v0.6.9 // indirect
|
||||||
github.com/liquidweb/liquidweb-go v1.6.4 // indirect
|
github.com/liquidweb/liquidweb-go v1.6.4 // indirect
|
||||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||||
|
@ -289,7 +289,7 @@ require (
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
|
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
|
||||||
github.com/oracle/oci-go-sdk/v65 v65.73.0 // indirect
|
github.com/oracle/oci-go-sdk/v65 v65.77.1 // indirect
|
||||||
github.com/ovh/go-ovh v1.6.0 // indirect
|
github.com/ovh/go-ovh v1.6.0 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||||
|
@ -299,7 +299,8 @@ require (
|
||||||
github.com/prometheus/common v0.55.0 // indirect
|
github.com/prometheus/common v0.55.0 // indirect
|
||||||
github.com/prometheus/procfs v0.15.1 // indirect
|
github.com/prometheus/procfs v0.15.1 // indirect
|
||||||
github.com/quic-go/qpack v0.5.1 // indirect
|
github.com/quic-go/qpack v0.5.1 // indirect
|
||||||
github.com/redis/go-redis/v9 v9.2.1 // indirect
|
github.com/redis/go-redis/v9 v9.6.1 // indirect
|
||||||
|
github.com/regfish/regfish-dnsapi-go v0.1.1 // indirect
|
||||||
github.com/rs/cors v1.7.0 // indirect
|
github.com/rs/cors v1.7.0 // indirect
|
||||||
github.com/sacloud/api-client-go v0.2.10 // indirect
|
github.com/sacloud/api-client-go v0.2.10 // indirect
|
||||||
github.com/sacloud/go-http v0.1.8 // indirect
|
github.com/sacloud/go-http v0.1.8 // indirect
|
||||||
|
@ -314,7 +315,7 @@ require (
|
||||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||||
github.com/shopspring/decimal v1.4.0 // indirect
|
github.com/shopspring/decimal v1.4.0 // indirect
|
||||||
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect
|
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect
|
||||||
github.com/softlayer/softlayer-go v1.1.5 // indirect
|
github.com/softlayer/softlayer-go v1.1.7 // indirect
|
||||||
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
|
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
|
||||||
github.com/sony/gobreaker v0.5.0 // indirect
|
github.com/sony/gobreaker v0.5.0 // indirect
|
||||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||||
|
@ -323,21 +324,22 @@ require (
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/spf13/viper v1.18.2 // indirect
|
github.com/spf13/viper v1.18.2 // indirect
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1002 // indirect
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1034 // indirect
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1002 // indirect
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1034 // indirect
|
||||||
github.com/tidwall/match v1.1.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
github.com/tidwall/pretty v1.2.1 // indirect
|
github.com/tidwall/pretty v1.2.1 // indirect
|
||||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||||
github.com/transip/gotransip/v6 v6.26.0 // indirect
|
github.com/transip/gotransip/v6 v6.26.0 // indirect
|
||||||
github.com/ultradns/ultradns-go-sdk v1.7.0-20240913052650-970ca9a // indirect
|
github.com/ultradns/ultradns-go-sdk v1.8.0-20241010134910-243eeec // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
|
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
|
||||||
|
github.com/volcengine/volc-sdk-golang v1.0.183 // indirect
|
||||||
github.com/vultr/govultr/v3 v3.9.1 // indirect
|
github.com/vultr/govultr/v3 v3.9.1 // indirect
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
github.com/yandex-cloud/go-genproto v0.0.0-20240911120709-1fa0cb6f47c2 // indirect
|
github.com/yandex-cloud/go-genproto v0.0.0-20241101135610-76a0cfc1a773 // indirect
|
||||||
github.com/yandex-cloud/go-sdk v0.0.0-20240911121212-e4e74d0d02f5 // indirect
|
github.com/yandex-cloud/go-sdk v0.0.0-20241101143304-947cf519f6bd // indirect
|
||||||
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
||||||
github.com/zeebo/errs v1.2.2 // indirect
|
github.com/zeebo/errs v1.2.2 // indirect
|
||||||
go.etcd.io/etcd/api/v3 v3.5.14 // indirect
|
go.etcd.io/etcd/api/v3 v3.5.14 // indirect
|
||||||
|
@ -357,19 +359,19 @@ require (
|
||||||
go.uber.org/ratelimit v0.3.0 // indirect
|
go.uber.org/ratelimit v0.3.0 // indirect
|
||||||
go.uber.org/zap v1.26.0 // indirect
|
go.uber.org/zap v1.26.0 // indirect
|
||||||
golang.org/x/arch v0.4.0 // indirect
|
golang.org/x/arch v0.4.0 // indirect
|
||||||
golang.org/x/crypto v0.27.0 // indirect
|
golang.org/x/crypto v0.28.0 // indirect
|
||||||
golang.org/x/oauth2 v0.23.0 // indirect
|
golang.org/x/oauth2 v0.23.0 // indirect
|
||||||
golang.org/x/term v0.24.0 // indirect
|
golang.org/x/term v0.25.0 // indirect
|
||||||
google.golang.org/api v0.197.0 // indirect
|
google.golang.org/api v0.204.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect
|
||||||
google.golang.org/protobuf v1.34.2 // indirect
|
google.golang.org/protobuf v1.35.1 // indirect
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||||
gopkg.in/h2non/gock.v1 v1.0.16 // indirect
|
gopkg.in/h2non/gock.v1 v1.0.16 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/ns1/ns1-go.v2 v2.12.0 // indirect
|
gopkg.in/ns1/ns1-go.v2 v2.12.2 // indirect
|
||||||
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
k8s.io/klog/v2 v2.130.1 // indirect
|
k8s.io/klog/v2 v2.130.1 // indirect
|
||||||
|
|
|
@ -41,7 +41,7 @@ func (s *HTTPSuite) TestSimpleConfiguration() {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"serviceHTTP": {
|
"serviceHTTP": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: boolRef(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://bacon:80",
|
URL: "http://bacon:80",
|
||||||
|
@ -81,6 +81,4 @@ func startTestServerWithResponse(response []byte) (ts *httptest.Server) {
|
||||||
return ts
|
return ts
|
||||||
}
|
}
|
||||||
|
|
||||||
func boolRef(b bool) *bool {
|
func pointer[T any](v T) *T { return &v }
|
||||||
return &b
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ package dashboard
|
||||||
import (
|
import (
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"strings"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/traefik/traefik/v3/webui"
|
"github.com/traefik/traefik/v3/webui"
|
||||||
|
@ -25,7 +25,8 @@ func Append(router *mux.Router, customAssets fs.FS) {
|
||||||
router.Methods(http.MethodGet).
|
router.Methods(http.MethodGet).
|
||||||
Path("/").
|
Path("/").
|
||||||
HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
|
HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
|
||||||
http.Redirect(resp, req, safePrefix(req)+"/dashboard/", http.StatusFound)
|
prefix := strings.TrimSuffix(req.Header.Get("X-Forwarded-Prefix"), "/")
|
||||||
|
http.Redirect(resp, req, prefix+"/dashboard/", http.StatusFound)
|
||||||
})
|
})
|
||||||
|
|
||||||
router.Methods(http.MethodGet).
|
router.Methods(http.MethodGet).
|
||||||
|
@ -58,21 +59,3 @@ func (g Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
http.FileServerFS(assets).ServeHTTP(w, r)
|
http.FileServerFS(assets).ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func safePrefix(req *http.Request) string {
|
|
||||||
prefix := req.Header.Get("X-Forwarded-Prefix")
|
|
||||||
if prefix == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
parse, err := url.Parse(prefix)
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if parse.Host != "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return parse.Path
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,53 +10,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_safePrefix(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
desc string
|
|
||||||
value string
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
desc: "host",
|
|
||||||
value: "https://example.com",
|
|
||||||
expected: "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "host with path",
|
|
||||||
value: "https://example.com/foo/bar?test",
|
|
||||||
expected: "",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "path",
|
|
||||||
value: "/foo/bar",
|
|
||||||
expected: "/foo/bar",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "path without leading slash",
|
|
||||||
value: "foo/bar",
|
|
||||||
expected: "foo/bar",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range testCases {
|
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
req, err := http.NewRequest(http.MethodGet, "http://localhost", nil)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
req.Header.Set("X-Forwarded-Prefix", test.value)
|
|
||||||
|
|
||||||
prefix := safePrefix(req)
|
|
||||||
|
|
||||||
assert.Equal(t, test.expected, prefix)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_ContentSecurityPolicy(t *testing.T) {
|
func Test_ContentSecurityPolicy(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
"github.com/traefik/traefik/v3/pkg/config/static"
|
"github.com/traefik/traefik/v3/pkg/config/static"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Bool(v bool) *bool { return &v }
|
func pointer[T any](v T) *T { return &v }
|
||||||
|
|
||||||
func TestHandler_HTTP(t *testing.T) {
|
func TestHandler_HTTP(t *testing.T) {
|
||||||
type expected struct {
|
type expected struct {
|
||||||
|
@ -415,7 +415,7 @@ func TestHandler_HTTP(t *testing.T) {
|
||||||
si := &runtime.ServiceInfo{
|
si := &runtime.ServiceInfo{
|
||||||
Service: &dynamic.Service{
|
Service: &dynamic.Service{
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://127.0.0.1",
|
URL: "http://127.0.0.1",
|
||||||
|
@ -432,7 +432,7 @@ func TestHandler_HTTP(t *testing.T) {
|
||||||
si := &runtime.ServiceInfo{
|
si := &runtime.ServiceInfo{
|
||||||
Service: &dynamic.Service{
|
Service: &dynamic.Service{
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://127.0.0.2",
|
URL: "http://127.0.0.2",
|
||||||
|
@ -501,7 +501,7 @@ func TestHandler_HTTP(t *testing.T) {
|
||||||
si := &runtime.ServiceInfo{
|
si := &runtime.ServiceInfo{
|
||||||
Service: &dynamic.Service{
|
Service: &dynamic.Service{
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://127.0.0.1",
|
URL: "http://127.0.0.1",
|
||||||
|
@ -518,7 +518,7 @@ func TestHandler_HTTP(t *testing.T) {
|
||||||
si := &runtime.ServiceInfo{
|
si := &runtime.ServiceInfo{
|
||||||
Service: &dynamic.Service{
|
Service: &dynamic.Service{
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://127.0.0.2",
|
URL: "http://127.0.0.2",
|
||||||
|
@ -535,7 +535,7 @@ func TestHandler_HTTP(t *testing.T) {
|
||||||
si := &runtime.ServiceInfo{
|
si := &runtime.ServiceInfo{
|
||||||
Service: &dynamic.Service{
|
Service: &dynamic.Service{
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://127.0.0.3",
|
URL: "http://127.0.0.3",
|
||||||
|
@ -565,7 +565,7 @@ func TestHandler_HTTP(t *testing.T) {
|
||||||
si := &runtime.ServiceInfo{
|
si := &runtime.ServiceInfo{
|
||||||
Service: &dynamic.Service{
|
Service: &dynamic.Service{
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://127.0.0.1",
|
URL: "http://127.0.0.1",
|
||||||
|
@ -583,7 +583,7 @@ func TestHandler_HTTP(t *testing.T) {
|
||||||
si := &runtime.ServiceInfo{
|
si := &runtime.ServiceInfo{
|
||||||
Service: &dynamic.Service{
|
Service: &dynamic.Service{
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://127.0.0.2",
|
URL: "http://127.0.0.2",
|
||||||
|
@ -614,7 +614,7 @@ func TestHandler_HTTP(t *testing.T) {
|
||||||
si := &runtime.ServiceInfo{
|
si := &runtime.ServiceInfo{
|
||||||
Service: &dynamic.Service{
|
Service: &dynamic.Service{
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://127.0.0.1",
|
URL: "http://127.0.0.1",
|
||||||
|
@ -632,7 +632,7 @@ func TestHandler_HTTP(t *testing.T) {
|
||||||
si := &runtime.ServiceInfo{
|
si := &runtime.ServiceInfo{
|
||||||
Service: &dynamic.Service{
|
Service: &dynamic.Service{
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://127.0.0.2",
|
URL: "http://127.0.0.2",
|
||||||
|
@ -663,7 +663,7 @@ func TestHandler_HTTP(t *testing.T) {
|
||||||
si := &runtime.ServiceInfo{
|
si := &runtime.ServiceInfo{
|
||||||
Service: &dynamic.Service{
|
Service: &dynamic.Service{
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://127.0.0.1",
|
URL: "http://127.0.0.1",
|
||||||
|
@ -692,7 +692,7 @@ func TestHandler_HTTP(t *testing.T) {
|
||||||
si := &runtime.ServiceInfo{
|
si := &runtime.ServiceInfo{
|
||||||
Service: &dynamic.Service{
|
Service: &dynamic.Service{
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://127.0.0.1",
|
URL: "http://127.0.0.1",
|
||||||
|
@ -721,7 +721,7 @@ func TestHandler_HTTP(t *testing.T) {
|
||||||
si := &runtime.ServiceInfo{
|
si := &runtime.ServiceInfo{
|
||||||
Service: &dynamic.Service{
|
Service: &dynamic.Service{
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://127.0.0.1",
|
URL: "http://127.0.0.1",
|
||||||
|
|
|
@ -38,7 +38,7 @@ func TestHandler_RawData(t *testing.T) {
|
||||||
"foo-service@myprovider": {
|
"foo-service@myprovider": {
|
||||||
Service: &dynamic.Service{
|
Service: &dynamic.Service{
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://127.0.0.1",
|
URL: "http://127.0.0.1",
|
||||||
|
|
|
@ -341,11 +341,7 @@ func (m tcpMiddlewareRepresentation) status() string {
|
||||||
return m.Status
|
return m.Status
|
||||||
}
|
}
|
||||||
|
|
||||||
type orderedByName interface {
|
func sortByName[T orderedWithName](direction string, results []T) {
|
||||||
orderedWithName
|
|
||||||
}
|
|
||||||
|
|
||||||
func sortByName[T orderedByName](direction string, results []T) {
|
|
||||||
// Ascending
|
// Ascending
|
||||||
if direction == ascendantSorting {
|
if direction == ascendantSorting {
|
||||||
sort.Slice(results, func(i, j int) bool {
|
sort.Slice(results, func(i, j int) bool {
|
||||||
|
|
|
@ -13,8 +13,7 @@ import (
|
||||||
"github.com/traefik/traefik/v3/pkg/types"
|
"github.com/traefik/traefik/v3/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Bool(v bool) *bool { return &v }
|
func pointer[T any](v T) *T { return &v }
|
||||||
func String(v string) *string { return &v }
|
|
||||||
|
|
||||||
func TestDecodeConfiguration(t *testing.T) {
|
func TestDecodeConfiguration(t *testing.T) {
|
||||||
labels := map[string]string{
|
labels := map[string]string{
|
||||||
|
@ -284,7 +283,7 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
Port: "42",
|
Port: "42",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
TerminationDelay: func(i int) *int { return &i }(42),
|
TerminationDelay: pointer(42),
|
||||||
ProxyProtocol: &dynamic.ProxyProtocol{Version: 42},
|
ProxyProtocol: &dynamic.ProxyProtocol{Version: 42},
|
||||||
ServersTransport: "foo",
|
ServersTransport: "foo",
|
||||||
},
|
},
|
||||||
|
@ -296,7 +295,7 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
Port: "42",
|
Port: "42",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
TerminationDelay: func(i int) *int { return &i }(42),
|
TerminationDelay: pointer(42),
|
||||||
ProxyProtocol: &dynamic.ProxyProtocol{Version: 2},
|
ProxyProtocol: &dynamic.ProxyProtocol{Version: 2},
|
||||||
ServersTransport: "foo",
|
ServersTransport: "foo",
|
||||||
},
|
},
|
||||||
|
@ -486,7 +485,7 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"fiibar",
|
"fiibar",
|
||||||
},
|
},
|
||||||
ForceSlash: Bool(true),
|
ForceSlash: pointer(true),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Middleware18": {
|
"Middleware18": {
|
||||||
|
@ -562,7 +561,7 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
Cert: "foobar",
|
Cert: "foobar",
|
||||||
Key: "foobar",
|
Key: "foobar",
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
CAOptional: Bool(true),
|
CAOptional: pointer(true),
|
||||||
},
|
},
|
||||||
TrustForwardHeader: true,
|
TrustForwardHeader: true,
|
||||||
AuthResponseHeaders: []string{
|
AuthResponseHeaders: []string{
|
||||||
|
@ -616,14 +615,14 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"fiibar",
|
"fiibar",
|
||||||
},
|
},
|
||||||
SSLRedirect: Bool(true),
|
SSLRedirect: pointer(true),
|
||||||
SSLTemporaryRedirect: Bool(true),
|
SSLTemporaryRedirect: pointer(true),
|
||||||
SSLHost: String("foobar"),
|
SSLHost: pointer("foobar"),
|
||||||
SSLProxyHeaders: map[string]string{
|
SSLProxyHeaders: map[string]string{
|
||||||
"name0": "foobar",
|
"name0": "foobar",
|
||||||
"name1": "foobar",
|
"name1": "foobar",
|
||||||
},
|
},
|
||||||
SSLForceHost: Bool(true),
|
SSLForceHost: pointer(true),
|
||||||
STSSeconds: 42,
|
STSSeconds: 42,
|
||||||
STSIncludeSubdomains: true,
|
STSIncludeSubdomains: true,
|
||||||
STSPreload: true,
|
STSPreload: true,
|
||||||
|
@ -637,7 +636,7 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
ContentSecurityPolicyReportOnly: "foobar",
|
ContentSecurityPolicyReportOnly: "foobar",
|
||||||
PublicKey: "foobar",
|
PublicKey: "foobar",
|
||||||
ReferrerPolicy: "foobar",
|
ReferrerPolicy: "foobar",
|
||||||
FeaturePolicy: String("foobar"),
|
FeaturePolicy: pointer("foobar"),
|
||||||
PermissionsPolicy: "foobar",
|
PermissionsPolicy: "foobar",
|
||||||
IsDevelopment: true,
|
IsDevelopment: true,
|
||||||
},
|
},
|
||||||
|
@ -698,9 +697,9 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"name0": "foobar",
|
"name0": "foobar",
|
||||||
"name1": "foobar",
|
"name1": "foobar",
|
||||||
},
|
},
|
||||||
FollowRedirects: func(v bool) *bool { return &v }(true),
|
FollowRedirects: pointer(true),
|
||||||
},
|
},
|
||||||
PassHostHeader: func(v bool) *bool { return &v }(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(time.Second),
|
FlushInterval: ptypes.Duration(time.Second),
|
||||||
},
|
},
|
||||||
|
@ -729,9 +728,9 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"name0": "foobar",
|
"name0": "foobar",
|
||||||
"name1": "foobar",
|
"name1": "foobar",
|
||||||
},
|
},
|
||||||
FollowRedirects: func(v bool) *bool { return &v }(true),
|
FollowRedirects: pointer(true),
|
||||||
},
|
},
|
||||||
PassHostHeader: func(v bool) *bool { return &v }(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(time.Second),
|
FlushInterval: ptypes.Duration(time.Second),
|
||||||
},
|
},
|
||||||
|
@ -812,7 +811,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ServersTransport: "foo",
|
ServersTransport: "foo",
|
||||||
TerminationDelay: func(i int) *int { return &i }(42),
|
TerminationDelay: pointer(42),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Service1": {
|
"Service1": {
|
||||||
|
@ -823,7 +822,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ServersTransport: "foo",
|
ServersTransport: "foo",
|
||||||
TerminationDelay: func(i int) *int { return &i }(42),
|
TerminationDelay: pointer(42),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1010,7 +1009,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"fiibar",
|
"fiibar",
|
||||||
},
|
},
|
||||||
ForceSlash: Bool(true),
|
ForceSlash: pointer(true),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Middleware18": {
|
"Middleware18": {
|
||||||
|
@ -1094,7 +1093,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
Cert: "foobar",
|
Cert: "foobar",
|
||||||
Key: "foobar",
|
Key: "foobar",
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
CAOptional: Bool(true),
|
CAOptional: pointer(true),
|
||||||
},
|
},
|
||||||
TrustForwardHeader: true,
|
TrustForwardHeader: true,
|
||||||
AuthResponseHeaders: []string{
|
AuthResponseHeaders: []string{
|
||||||
|
@ -1148,14 +1147,14 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"fiibar",
|
"fiibar",
|
||||||
},
|
},
|
||||||
SSLRedirect: Bool(true),
|
SSLRedirect: pointer(true),
|
||||||
SSLTemporaryRedirect: Bool(true),
|
SSLTemporaryRedirect: pointer(true),
|
||||||
SSLHost: String("foobar"),
|
SSLHost: pointer("foobar"),
|
||||||
SSLProxyHeaders: map[string]string{
|
SSLProxyHeaders: map[string]string{
|
||||||
"name0": "foobar",
|
"name0": "foobar",
|
||||||
"name1": "foobar",
|
"name1": "foobar",
|
||||||
},
|
},
|
||||||
SSLForceHost: Bool(true),
|
SSLForceHost: pointer(true),
|
||||||
STSSeconds: 42,
|
STSSeconds: 42,
|
||||||
STSIncludeSubdomains: true,
|
STSIncludeSubdomains: true,
|
||||||
STSPreload: true,
|
STSPreload: true,
|
||||||
|
@ -1169,7 +1168,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
ContentSecurityPolicyReportOnly: "foobar",
|
ContentSecurityPolicyReportOnly: "foobar",
|
||||||
PublicKey: "foobar",
|
PublicKey: "foobar",
|
||||||
ReferrerPolicy: "foobar",
|
ReferrerPolicy: "foobar",
|
||||||
FeaturePolicy: String("foobar"),
|
FeaturePolicy: pointer("foobar"),
|
||||||
PermissionsPolicy: "foobar",
|
PermissionsPolicy: "foobar",
|
||||||
IsDevelopment: true,
|
IsDevelopment: true,
|
||||||
},
|
},
|
||||||
|
@ -1221,7 +1220,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"name1": "foobar",
|
"name1": "foobar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: func(v bool) *bool { return &v }(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(time.Second),
|
FlushInterval: ptypes.Duration(time.Second),
|
||||||
},
|
},
|
||||||
|
@ -1250,7 +1249,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"name1": "foobar",
|
"name1": "foobar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: func(v bool) *bool { return &v }(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(time.Second),
|
FlushInterval: ptypes.Duration(time.Second),
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,14 +27,14 @@ type EntryPoint struct {
|
||||||
|
|
||||||
// GetAddress strips any potential protocol part of the address field of the
|
// GetAddress strips any potential protocol part of the address field of the
|
||||||
// entry point, in order to return the actual address.
|
// entry point, in order to return the actual address.
|
||||||
func (ep EntryPoint) GetAddress() string {
|
func (ep *EntryPoint) GetAddress() string {
|
||||||
splitN := strings.SplitN(ep.Address, "/", 2)
|
splitN := strings.SplitN(ep.Address, "/", 2)
|
||||||
return splitN[0]
|
return splitN[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetProtocol returns the protocol part of the address field of the entry point.
|
// GetProtocol returns the protocol part of the address field of the entry point.
|
||||||
// If none is specified, it defaults to "tcp".
|
// If none is specified, it defaults to "tcp".
|
||||||
func (ep EntryPoint) GetProtocol() (string, error) {
|
func (ep *EntryPoint) GetProtocol() (string, error) {
|
||||||
splitN := strings.SplitN(ep.Address, "/", 2)
|
splitN := strings.SplitN(ep.Address, "/", 2)
|
||||||
if len(splitN) < 2 {
|
if len(splitN) < 2 {
|
||||||
return "tcp", nil
|
return "tcp", nil
|
||||||
|
|
|
@ -297,6 +297,12 @@ func (c *Configuration) SetEffectiveConfiguration() {
|
||||||
c.Providers.KubernetesGateway.EntryPoints = entryPoints
|
c.Providers.KubernetesGateway.EntryPoints = entryPoints
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Defines the default rule syntax for the Kubernetes Ingress Provider.
|
||||||
|
// This allows the provider to adapt the matcher syntax to the desired rule syntax version.
|
||||||
|
if c.Core != nil && c.Providers.KubernetesIngress != nil {
|
||||||
|
c.Providers.KubernetesIngress.DefaultRuleSyntax = c.Core.DefaultRuleSyntax
|
||||||
|
}
|
||||||
|
|
||||||
c.initACMEProvider()
|
c.initACMEProvider()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@ import (
|
||||||
|
|
||||||
const delta float64 = 1e-10
|
const delta float64 = 1e-10
|
||||||
|
|
||||||
|
func pointer[T any](v T) *T { return &v }
|
||||||
|
|
||||||
func TestNewServiceHealthChecker_durations(t *testing.T) {
|
func TestNewServiceHealthChecker_durations(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
|
@ -285,7 +287,7 @@ func TestServiceHealthChecker_checkHealthHTTP_NotFollowingRedirects(t *testing.T
|
||||||
|
|
||||||
config := &dynamic.ServerHealthCheck{
|
config := &dynamic.ServerHealthCheck{
|
||||||
Path: "/path",
|
Path: "/path",
|
||||||
FollowRedirects: Bool(false),
|
FollowRedirects: pointer(false),
|
||||||
Interval: dynamic.DefaultHealthCheckInterval,
|
Interval: dynamic.DefaultHealthCheckInterval,
|
||||||
Timeout: dynamic.DefaultHealthCheckTimeout,
|
Timeout: dynamic.DefaultHealthCheckTimeout,
|
||||||
}
|
}
|
||||||
|
@ -454,7 +456,3 @@ func TestServiceHealthChecker_Launch(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Bool(b bool) *bool {
|
|
||||||
return &b
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -812,10 +811,10 @@ func assertValidLogData(t *testing.T, expected string, logData []byte) {
|
||||||
assert.Equal(t, resultExpected[OriginContentSize], result[OriginContentSize], formatErrMessage)
|
assert.Equal(t, resultExpected[OriginContentSize], result[OriginContentSize], formatErrMessage)
|
||||||
assert.Equal(t, resultExpected[RequestRefererHeader], result[RequestRefererHeader], formatErrMessage)
|
assert.Equal(t, resultExpected[RequestRefererHeader], result[RequestRefererHeader], formatErrMessage)
|
||||||
assert.Equal(t, resultExpected[RequestUserAgentHeader], result[RequestUserAgentHeader], formatErrMessage)
|
assert.Equal(t, resultExpected[RequestUserAgentHeader], result[RequestUserAgentHeader], formatErrMessage)
|
||||||
assert.Regexp(t, regexp.MustCompile(`\d*`), result[RequestCount], formatErrMessage)
|
assert.Regexp(t, `\d*`, result[RequestCount], formatErrMessage)
|
||||||
assert.Equal(t, resultExpected[RouterName], result[RouterName], formatErrMessage)
|
assert.Equal(t, resultExpected[RouterName], result[RouterName], formatErrMessage)
|
||||||
assert.Equal(t, resultExpected[ServiceURL], result[ServiceURL], formatErrMessage)
|
assert.Equal(t, resultExpected[ServiceURL], result[ServiceURL], formatErrMessage)
|
||||||
assert.Regexp(t, regexp.MustCompile(`\d*ms`), result[Duration], formatErrMessage)
|
assert.Regexp(t, `\d*ms`, result[Duration], formatErrMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
func captureStdout(t *testing.T) (out *os.File, restoreStdout func()) {
|
func captureStdout(t *testing.T) (out *os.File, restoreStdout func()) {
|
||||||
|
|
|
@ -20,6 +20,7 @@ const (
|
||||||
xForwardedServer = "X-Forwarded-Server"
|
xForwardedServer = "X-Forwarded-Server"
|
||||||
xForwardedURI = "X-Forwarded-Uri"
|
xForwardedURI = "X-Forwarded-Uri"
|
||||||
xForwardedMethod = "X-Forwarded-Method"
|
xForwardedMethod = "X-Forwarded-Method"
|
||||||
|
xForwardedPrefix = "X-Forwarded-Prefix"
|
||||||
xForwardedTLSClientCert = "X-Forwarded-Tls-Client-Cert"
|
xForwardedTLSClientCert = "X-Forwarded-Tls-Client-Cert"
|
||||||
xForwardedTLSClientCertInfo = "X-Forwarded-Tls-Client-Cert-Info"
|
xForwardedTLSClientCertInfo = "X-Forwarded-Tls-Client-Cert-Info"
|
||||||
xRealIP = "X-Real-Ip"
|
xRealIP = "X-Real-Ip"
|
||||||
|
@ -35,6 +36,7 @@ var xHeaders = []string{
|
||||||
xForwardedServer,
|
xForwardedServer,
|
||||||
xForwardedURI,
|
xForwardedURI,
|
||||||
xForwardedMethod,
|
xForwardedMethod,
|
||||||
|
xForwardedPrefix,
|
||||||
xForwardedTLSClientCert,
|
xForwardedTLSClientCert,
|
||||||
xForwardedTLSClientCertInfo,
|
xForwardedTLSClientCertInfo,
|
||||||
xRealIP,
|
xRealIP,
|
||||||
|
|
|
@ -48,6 +48,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedMethod: {"GET"},
|
xForwardedMethod: {"GET"},
|
||||||
xForwardedTLSClientCert: {"Cert"},
|
xForwardedTLSClientCert: {"Cert"},
|
||||||
xForwardedTLSClientCertInfo: {"CertInfo"},
|
xForwardedTLSClientCertInfo: {"CertInfo"},
|
||||||
|
xForwardedPrefix: {"/prefix"},
|
||||||
},
|
},
|
||||||
expectedHeaders: map[string]string{
|
expectedHeaders: map[string]string{
|
||||||
xForwardedFor: "10.0.1.0, 10.0.1.12",
|
xForwardedFor: "10.0.1.0, 10.0.1.12",
|
||||||
|
@ -55,6 +56,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedMethod: "GET",
|
xForwardedMethod: "GET",
|
||||||
xForwardedTLSClientCert: "Cert",
|
xForwardedTLSClientCert: "Cert",
|
||||||
xForwardedTLSClientCertInfo: "CertInfo",
|
xForwardedTLSClientCertInfo: "CertInfo",
|
||||||
|
xForwardedPrefix: "/prefix",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -68,6 +70,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedMethod: {"GET"},
|
xForwardedMethod: {"GET"},
|
||||||
xForwardedTLSClientCert: {"Cert"},
|
xForwardedTLSClientCert: {"Cert"},
|
||||||
xForwardedTLSClientCertInfo: {"CertInfo"},
|
xForwardedTLSClientCertInfo: {"CertInfo"},
|
||||||
|
xForwardedPrefix: {"/prefix"},
|
||||||
},
|
},
|
||||||
expectedHeaders: map[string]string{
|
expectedHeaders: map[string]string{
|
||||||
xForwardedFor: "",
|
xForwardedFor: "",
|
||||||
|
@ -75,6 +78,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedMethod: "",
|
xForwardedMethod: "",
|
||||||
xForwardedTLSClientCert: "",
|
xForwardedTLSClientCert: "",
|
||||||
xForwardedTLSClientCertInfo: "",
|
xForwardedTLSClientCertInfo: "",
|
||||||
|
xForwardedPrefix: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -88,6 +92,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedMethod: {"GET"},
|
xForwardedMethod: {"GET"},
|
||||||
xForwardedTLSClientCert: {"Cert"},
|
xForwardedTLSClientCert: {"Cert"},
|
||||||
xForwardedTLSClientCertInfo: {"CertInfo"},
|
xForwardedTLSClientCertInfo: {"CertInfo"},
|
||||||
|
xForwardedPrefix: {"/prefix"},
|
||||||
},
|
},
|
||||||
expectedHeaders: map[string]string{
|
expectedHeaders: map[string]string{
|
||||||
xForwardedFor: "10.0.1.0, 10.0.1.12",
|
xForwardedFor: "10.0.1.0, 10.0.1.12",
|
||||||
|
@ -95,6 +100,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedMethod: "GET",
|
xForwardedMethod: "GET",
|
||||||
xForwardedTLSClientCert: "Cert",
|
xForwardedTLSClientCert: "Cert",
|
||||||
xForwardedTLSClientCertInfo: "CertInfo",
|
xForwardedTLSClientCertInfo: "CertInfo",
|
||||||
|
xForwardedPrefix: "/prefix",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -108,6 +114,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedMethod: {"GET"},
|
xForwardedMethod: {"GET"},
|
||||||
xForwardedTLSClientCert: {"Cert"},
|
xForwardedTLSClientCert: {"Cert"},
|
||||||
xForwardedTLSClientCertInfo: {"CertInfo"},
|
xForwardedTLSClientCertInfo: {"CertInfo"},
|
||||||
|
xForwardedPrefix: {"/prefix"},
|
||||||
},
|
},
|
||||||
expectedHeaders: map[string]string{
|
expectedHeaders: map[string]string{
|
||||||
xForwardedFor: "",
|
xForwardedFor: "",
|
||||||
|
@ -115,6 +122,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedMethod: "",
|
xForwardedMethod: "",
|
||||||
xForwardedTLSClientCert: "",
|
xForwardedTLSClientCert: "",
|
||||||
xForwardedTLSClientCertInfo: "",
|
xForwardedTLSClientCertInfo: "",
|
||||||
|
xForwardedPrefix: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -128,6 +136,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedMethod: {"GET"},
|
xForwardedMethod: {"GET"},
|
||||||
xForwardedTLSClientCert: {"Cert"},
|
xForwardedTLSClientCert: {"Cert"},
|
||||||
xForwardedTLSClientCertInfo: {"CertInfo"},
|
xForwardedTLSClientCertInfo: {"CertInfo"},
|
||||||
|
xForwardedPrefix: {"/prefix"},
|
||||||
},
|
},
|
||||||
expectedHeaders: map[string]string{
|
expectedHeaders: map[string]string{
|
||||||
xForwardedFor: "10.0.1.0, 10.0.1.12",
|
xForwardedFor: "10.0.1.0, 10.0.1.12",
|
||||||
|
@ -135,6 +144,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedMethod: "GET",
|
xForwardedMethod: "GET",
|
||||||
xForwardedTLSClientCert: "Cert",
|
xForwardedTLSClientCert: "Cert",
|
||||||
xForwardedTLSClientCertInfo: "CertInfo",
|
xForwardedTLSClientCertInfo: "CertInfo",
|
||||||
|
xForwardedPrefix: "/prefix",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -148,6 +158,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedMethod: {"GET"},
|
xForwardedMethod: {"GET"},
|
||||||
xForwardedTLSClientCert: {"Cert"},
|
xForwardedTLSClientCert: {"Cert"},
|
||||||
xForwardedTLSClientCertInfo: {"CertInfo"},
|
xForwardedTLSClientCertInfo: {"CertInfo"},
|
||||||
|
xForwardedPrefix: {"/prefix"},
|
||||||
},
|
},
|
||||||
expectedHeaders: map[string]string{
|
expectedHeaders: map[string]string{
|
||||||
xForwardedFor: "",
|
xForwardedFor: "",
|
||||||
|
@ -155,6 +166,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedMethod: "",
|
xForwardedMethod: "",
|
||||||
xForwardedTLSClientCert: "",
|
xForwardedTLSClientCert: "",
|
||||||
xForwardedTLSClientCertInfo: "",
|
xForwardedTLSClientCertInfo: "",
|
||||||
|
xForwardedPrefix: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -283,6 +295,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedPort,
|
xForwardedPort,
|
||||||
xForwardedTLSClientCert,
|
xForwardedTLSClientCert,
|
||||||
xForwardedTLSClientCertInfo,
|
xForwardedTLSClientCertInfo,
|
||||||
|
xForwardedPrefix,
|
||||||
xRealIP,
|
xRealIP,
|
||||||
},
|
},
|
||||||
xForwardedProto: {"foo"},
|
xForwardedProto: {"foo"},
|
||||||
|
@ -293,6 +306,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedPort: {"foo"},
|
xForwardedPort: {"foo"},
|
||||||
xForwardedTLSClientCert: {"foo"},
|
xForwardedTLSClientCert: {"foo"},
|
||||||
xForwardedTLSClientCertInfo: {"foo"},
|
xForwardedTLSClientCertInfo: {"foo"},
|
||||||
|
xForwardedPrefix: {"foo"},
|
||||||
xRealIP: {"foo"},
|
xRealIP: {"foo"},
|
||||||
},
|
},
|
||||||
expectedHeaders: map[string]string{
|
expectedHeaders: map[string]string{
|
||||||
|
@ -304,6 +318,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedPort: "80",
|
xForwardedPort: "80",
|
||||||
xForwardedTLSClientCert: "",
|
xForwardedTLSClientCert: "",
|
||||||
xForwardedTLSClientCertInfo: "",
|
xForwardedTLSClientCertInfo: "",
|
||||||
|
xForwardedPrefix: "",
|
||||||
xRealIP: "",
|
xRealIP: "",
|
||||||
connection: "",
|
connection: "",
|
||||||
},
|
},
|
||||||
|
@ -321,6 +336,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedPort,
|
xForwardedPort,
|
||||||
xForwardedTLSClientCert,
|
xForwardedTLSClientCert,
|
||||||
xForwardedTLSClientCertInfo,
|
xForwardedTLSClientCertInfo,
|
||||||
|
xForwardedPrefix,
|
||||||
xRealIP,
|
xRealIP,
|
||||||
},
|
},
|
||||||
xForwardedProto: {"foo"},
|
xForwardedProto: {"foo"},
|
||||||
|
@ -331,6 +347,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedPort: {"foo"},
|
xForwardedPort: {"foo"},
|
||||||
xForwardedTLSClientCert: {"foo"},
|
xForwardedTLSClientCert: {"foo"},
|
||||||
xForwardedTLSClientCertInfo: {"foo"},
|
xForwardedTLSClientCertInfo: {"foo"},
|
||||||
|
xForwardedPrefix: {"foo"},
|
||||||
xRealIP: {"foo"},
|
xRealIP: {"foo"},
|
||||||
},
|
},
|
||||||
expectedHeaders: map[string]string{
|
expectedHeaders: map[string]string{
|
||||||
|
@ -342,6 +359,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedPort: "foo",
|
xForwardedPort: "foo",
|
||||||
xForwardedTLSClientCert: "foo",
|
xForwardedTLSClientCert: "foo",
|
||||||
xForwardedTLSClientCertInfo: "foo",
|
xForwardedTLSClientCertInfo: "foo",
|
||||||
|
xForwardedPrefix: "foo",
|
||||||
xRealIP: "foo",
|
xRealIP: "foo",
|
||||||
connection: "",
|
connection: "",
|
||||||
},
|
},
|
||||||
|
@ -358,6 +376,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedPort,
|
xForwardedPort,
|
||||||
xForwardedTLSClientCert,
|
xForwardedTLSClientCert,
|
||||||
xForwardedTLSClientCertInfo,
|
xForwardedTLSClientCertInfo,
|
||||||
|
xForwardedPrefix,
|
||||||
xRealIP,
|
xRealIP,
|
||||||
},
|
},
|
||||||
incomingHeaders: map[string][]string{
|
incomingHeaders: map[string][]string{
|
||||||
|
@ -370,6 +389,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedPort,
|
xForwardedPort,
|
||||||
xForwardedTLSClientCert,
|
xForwardedTLSClientCert,
|
||||||
xForwardedTLSClientCertInfo,
|
xForwardedTLSClientCertInfo,
|
||||||
|
xForwardedPrefix,
|
||||||
xRealIP,
|
xRealIP,
|
||||||
},
|
},
|
||||||
xForwardedProto: {"foo"},
|
xForwardedProto: {"foo"},
|
||||||
|
@ -380,6 +400,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedPort: {"foo"},
|
xForwardedPort: {"foo"},
|
||||||
xForwardedTLSClientCert: {"foo"},
|
xForwardedTLSClientCert: {"foo"},
|
||||||
xForwardedTLSClientCertInfo: {"foo"},
|
xForwardedTLSClientCertInfo: {"foo"},
|
||||||
|
xForwardedPrefix: {"foo"},
|
||||||
xRealIP: {"foo"},
|
xRealIP: {"foo"},
|
||||||
},
|
},
|
||||||
expectedHeaders: map[string]string{
|
expectedHeaders: map[string]string{
|
||||||
|
@ -391,6 +412,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedPort: "80",
|
xForwardedPort: "80",
|
||||||
xForwardedTLSClientCert: "",
|
xForwardedTLSClientCert: "",
|
||||||
xForwardedTLSClientCertInfo: "",
|
xForwardedTLSClientCertInfo: "",
|
||||||
|
xForwardedPrefix: "",
|
||||||
xRealIP: "",
|
xRealIP: "",
|
||||||
connection: "",
|
connection: "",
|
||||||
},
|
},
|
||||||
|
@ -407,6 +429,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedPort,
|
xForwardedPort,
|
||||||
xForwardedTLSClientCert,
|
xForwardedTLSClientCert,
|
||||||
xForwardedTLSClientCertInfo,
|
xForwardedTLSClientCertInfo,
|
||||||
|
xForwardedPrefix,
|
||||||
xRealIP,
|
xRealIP,
|
||||||
},
|
},
|
||||||
incomingHeaders: map[string][]string{
|
incomingHeaders: map[string][]string{
|
||||||
|
@ -419,6 +442,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedPort,
|
xForwardedPort,
|
||||||
xForwardedTLSClientCert,
|
xForwardedTLSClientCert,
|
||||||
xForwardedTLSClientCertInfo,
|
xForwardedTLSClientCertInfo,
|
||||||
|
xForwardedPrefix,
|
||||||
xRealIP,
|
xRealIP,
|
||||||
},
|
},
|
||||||
xForwardedProto: {"foo"},
|
xForwardedProto: {"foo"},
|
||||||
|
@ -429,6 +453,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedPort: {"foo"},
|
xForwardedPort: {"foo"},
|
||||||
xForwardedTLSClientCert: {"foo"},
|
xForwardedTLSClientCert: {"foo"},
|
||||||
xForwardedTLSClientCertInfo: {"foo"},
|
xForwardedTLSClientCertInfo: {"foo"},
|
||||||
|
xForwardedPrefix: {"foo"},
|
||||||
xRealIP: {"foo"},
|
xRealIP: {"foo"},
|
||||||
},
|
},
|
||||||
expectedHeaders: map[string]string{
|
expectedHeaders: map[string]string{
|
||||||
|
@ -440,6 +465,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
xForwardedPort: "foo",
|
xForwardedPort: "foo",
|
||||||
xForwardedTLSClientCert: "foo",
|
xForwardedTLSClientCert: "foo",
|
||||||
xForwardedTLSClientCertInfo: "foo",
|
xForwardedTLSClientCertInfo: "foo",
|
||||||
|
xForwardedPrefix: "foo",
|
||||||
xRealIP: "foo",
|
xRealIP: "foo",
|
||||||
connection: "",
|
connection: "",
|
||||||
},
|
},
|
||||||
|
|
|
@ -76,7 +76,7 @@ func NewMuxer() (*Muxer, error) {
|
||||||
|
|
||||||
// Match returns the handler of the first route matching the connection metadata,
|
// Match returns the handler of the first route matching the connection metadata,
|
||||||
// and whether the match is exactly from the rule HostSNI(*).
|
// and whether the match is exactly from the rule HostSNI(*).
|
||||||
func (m Muxer) Match(meta ConnData) (tcp.Handler, bool) {
|
func (m *Muxer) Match(meta ConnData) (tcp.Handler, bool) {
|
||||||
for _, route := range m.routes {
|
for _, route := range m.routes {
|
||||||
if route.matchers.match(meta) {
|
if route.matchers.match(meta) {
|
||||||
return route.handler, route.catchAll
|
return route.handler, route.catchAll
|
||||||
|
|
|
@ -67,8 +67,8 @@ type ProviderAggregator struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProviderAggregator returns an aggregate of all the providers configured in the static configuration.
|
// NewProviderAggregator returns an aggregate of all the providers configured in the static configuration.
|
||||||
func NewProviderAggregator(conf static.Providers) ProviderAggregator {
|
func NewProviderAggregator(conf static.Providers) *ProviderAggregator {
|
||||||
p := ProviderAggregator{
|
p := &ProviderAggregator{
|
||||||
providersThrottleDuration: time.Duration(conf.ProvidersThrottleDuration),
|
providersThrottleDuration: time.Duration(conf.ProvidersThrottleDuration),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,12 +168,12 @@ func (p *ProviderAggregator) AddProvider(provider provider.Provider) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init the provider.
|
// Init the provider.
|
||||||
func (p ProviderAggregator) Init() error {
|
func (p *ProviderAggregator) Init() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide calls the provide method of every providers.
|
// Provide calls the provide method of every providers.
|
||||||
func (p ProviderAggregator) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {
|
func (p *ProviderAggregator) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {
|
||||||
if p.fileProvider != nil {
|
if p.fileProvider != nil {
|
||||||
p.launchProvider(configurationChan, pool, p.fileProvider)
|
p.launchProvider(configurationChan, pool, p.fileProvider)
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ func (p ProviderAggregator) Provide(configurationChan chan<- dynamic.Message, po
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p ProviderAggregator) launchProvider(configurationChan chan<- dynamic.Message, pool *safe.Pool, prd provider.Provider) {
|
func (p *ProviderAggregator) launchProvider(configurationChan chan<- dynamic.Message, pool *safe.Pool, prd provider.Provider) {
|
||||||
jsonConf, err := redactor.RemoveCredentials(prd)
|
jsonConf, err := redactor.RemoveCredentials(prd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug().Err(err).Msgf("Cannot marshal the provider configuration %T", prd)
|
log.Debug().Err(err).Msgf("Cannot marshal the provider configuration %T", prd)
|
||||||
|
|
|
@ -15,8 +15,7 @@ import (
|
||||||
"github.com/traefik/traefik/v3/pkg/types"
|
"github.com/traefik/traefik/v3/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Int(v int) *int { return &v }
|
func pointer[T any](v T) *T { return &v }
|
||||||
func Bool(v bool) *bool { return &v }
|
|
||||||
|
|
||||||
func TestDefaultRule(t *testing.T) {
|
func TestDefaultRule(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
|
@ -67,7 +66,7 @@ func TestDefaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -125,7 +124,7 @@ func TestDefaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -175,7 +174,7 @@ func TestDefaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -225,7 +224,7 @@ func TestDefaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -281,7 +280,7 @@ func TestDefaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -375,7 +374,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -436,7 +435,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "https://127.0.0.1:443",
|
URL: "https://127.0.0.1:443",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -530,7 +529,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "https://127.0.0.2:444",
|
URL: "https://127.0.0.2:444",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -615,7 +614,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -628,7 +627,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -695,7 +694,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -759,7 +758,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -826,7 +825,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -882,7 +881,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -939,7 +938,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -988,7 +987,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1050,7 +1049,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1102,7 +1101,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1115,7 +1114,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1297,7 +1296,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1352,7 +1351,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1433,7 +1432,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1501,7 +1500,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1585,7 +1584,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.3:80",
|
URL: "http://127.0.0.3:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1649,7 +1648,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1727,7 +1726,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.3:80",
|
URL: "http://127.0.0.3:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1797,7 +1796,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1853,7 +1852,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1910,7 +1909,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "h2c://127.0.0.1:8080",
|
URL: "h2c://127.0.0.1:8080",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1961,7 +1960,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1974,7 +1973,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:8080",
|
URL: "http://127.0.0.1:8080",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2207,7 +2206,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2274,7 +2273,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2710,7 +2709,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2801,7 +2800,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3019,7 +3018,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "https://127.0.0.1:80",
|
URL: "https://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3033,7 +3032,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "https://127.0.0.2:80",
|
URL: "https://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3319,7 +3318,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3495,7 +3494,7 @@ func TestFilterHealthStatuses(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3508,7 +3507,7 @@ func TestFilterHealthStatuses(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:81",
|
URL: "http://127.0.0.1:81",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3611,7 +3610,7 @@ func TestFilterHealthStatuses(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:81",
|
URL: "http://127.0.0.1:81",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3691,7 +3690,7 @@ func TestFilterHealthStatuses(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3704,7 +3703,7 @@ func TestFilterHealthStatuses(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:81",
|
URL: "http://127.0.0.1:81",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3803,7 +3802,7 @@ func TestFilterHealthStatuses(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3816,7 +3815,7 @@ func TestFilterHealthStatuses(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:81",
|
URL: "http://127.0.0.1:81",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3829,7 +3828,7 @@ func TestFilterHealthStatuses(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:82",
|
URL: "http://127.0.0.1:82",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3842,7 +3841,7 @@ func TestFilterHealthStatuses(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:83",
|
URL: "http://127.0.0.1:83",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
|
|
@ -74,7 +74,7 @@ func TestDynConfBuilder_DefaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -137,7 +137,7 @@ func TestDynConfBuilder_DefaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -202,7 +202,7 @@ func TestDynConfBuilder_DefaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -259,7 +259,7 @@ func TestDynConfBuilder_DefaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -316,7 +316,7 @@ func TestDynConfBuilder_DefaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -379,7 +379,7 @@ func TestDynConfBuilder_DefaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -613,7 +613,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -696,7 +696,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -709,7 +709,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -792,7 +792,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -856,7 +856,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -921,7 +921,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -978,7 +978,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1048,7 +1048,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1108,7 +1108,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1121,7 +1121,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1185,7 +1185,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1431,7 +1431,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1494,7 +1494,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1594,7 +1594,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1681,7 +1681,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1790,7 +1790,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.3:80",
|
URL: "http://127.0.0.3:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1871,7 +1871,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1974,7 +1974,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.3:80",
|
URL: "http://127.0.0.3:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2060,7 +2060,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2136,7 +2136,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2149,7 +2149,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2213,7 +2213,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2278,7 +2278,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "h2c://127.0.0.1:8080",
|
URL: "h2c://127.0.0.1:8080",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2337,7 +2337,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2350,7 +2350,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:8080",
|
URL: "http://127.0.0.1:8080",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2554,7 +2554,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"Test": {
|
"Test": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2819,7 +2819,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2894,7 +2894,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3368,7 +3368,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3549,7 +3549,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://192.168.0.1:8081",
|
URL: "http://192.168.0.1:8081",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3612,7 +3612,7 @@ func TestDynConfBuilder_build(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:79",
|
URL: "http://127.0.0.1:79",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -4031,6 +4031,4 @@ func TestDynConfBuilder_getIPAddress_swarm(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Int(v int) *int { return &v }
|
func pointer[T any](v T) *T { return &v }
|
||||||
|
|
||||||
func Bool(v bool) *bool { return &v }
|
|
||||||
|
|
|
@ -14,8 +14,7 @@ import (
|
||||||
"github.com/traefik/traefik/v3/pkg/types"
|
"github.com/traefik/traefik/v3/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Int(v int) *int { return &v }
|
func pointer[T any](v T) *T { return &v }
|
||||||
func Bool(v bool) *bool { return &v }
|
|
||||||
|
|
||||||
func TestDefaultRule(t *testing.T) {
|
func TestDefaultRule(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
|
@ -69,7 +68,7 @@ func TestDefaultRule(t *testing.T) {
|
||||||
URL: "http://10.0.0.1:1337",
|
URL: "http://10.0.0.1:1337",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -127,7 +126,7 @@ func TestDefaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -187,7 +186,7 @@ func TestDefaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -239,7 +238,7 @@ func TestDefaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -291,7 +290,7 @@ func TestDefaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -349,7 +348,7 @@ func TestDefaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -558,7 +557,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -631,7 +630,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -644,7 +643,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -717,7 +716,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -776,7 +775,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -836,7 +835,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -888,7 +887,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -953,7 +952,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1008,7 +1007,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1021,7 +1020,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1080,7 +1079,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1291,7 +1290,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1349,7 +1348,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1439,7 +1438,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1516,7 +1515,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1610,7 +1609,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.3:80",
|
URL: "http://127.0.0.3:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1681,7 +1680,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1769,7 +1768,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.3:80",
|
URL: "http://127.0.0.3:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1846,7 +1845,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1912,7 +1911,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1925,7 +1924,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1984,7 +1983,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2044,7 +2043,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "h2c://127.0.0.1:8080",
|
URL: "h2c://127.0.0.1:8080",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2104,7 +2103,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "h2c://127.0.0.1:8040",
|
URL: "h2c://127.0.0.1:8040",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2172,7 +2171,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:32124",
|
URL: "http://127.0.0.1:32124",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2185,7 +2184,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:32123",
|
URL: "http://127.0.0.1:32123",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2239,7 +2238,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2252,7 +2251,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:8080",
|
URL: "http://127.0.0.1:8080",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2542,7 +2541,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2612,7 +2611,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3046,7 +3045,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3206,7 +3205,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
|
|
@ -396,7 +396,7 @@ func (c configBuilder) buildServersLB(namespace string, svc traefikv1alpha1.Load
|
||||||
return &dynamic.Service{LoadBalancer: lb}, nil
|
return &dynamic.Service{LoadBalancer: lb}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *configBuilder) makeServersTransportKey(parentNamespace string, serversTransportName string) (string, error) {
|
func (c configBuilder) makeServersTransportKey(parentNamespace string, serversTransportName string) (string, error) {
|
||||||
if serversTransportName == "" {
|
if serversTransportName == "" {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -128,8 +128,8 @@ func Test_parseServiceConfig(t *testing.T) {
|
||||||
},
|
},
|
||||||
ServersScheme: "protocol",
|
ServersScheme: "protocol",
|
||||||
ServersTransport: "foobar@file",
|
ServersTransport: "foobar@file",
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
NativeLB: Bool(true),
|
NativeLB: pointer(true),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -145,7 +145,7 @@ func Test_parseServiceConfig(t *testing.T) {
|
||||||
Path: String("/"),
|
Path: String("/"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
kind: Ingress
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: ""
|
||||||
|
namespace: testing
|
||||||
|
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: "*.foobar.com"
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /bar
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: service1
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
pathType: Prefix
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: Service
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: service1
|
||||||
|
namespace: testing
|
||||||
|
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
clusterIP: 10.0.0.1
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: EndpointSlice
|
||||||
|
apiVersion: discovery.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: service1-abc
|
||||||
|
namespace: testing
|
||||||
|
labels:
|
||||||
|
kubernetes.io/service-name: service1
|
||||||
|
|
||||||
|
addressType: IPv4
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
name: ""
|
||||||
|
endpoints:
|
||||||
|
- addresses:
|
||||||
|
- 10.10.0.1
|
||||||
|
conditions:
|
||||||
|
ready: true
|
|
@ -56,6 +56,9 @@ type Provider struct {
|
||||||
DisableClusterScopeResources bool `description:"Disables the lookup of cluster scope resources (incompatible with IngressClasses and NodePortLB enabled services)." json:"disableClusterScopeResources,omitempty" toml:"disableClusterScopeResources,omitempty" yaml:"disableClusterScopeResources,omitempty" export:"true"`
|
DisableClusterScopeResources bool `description:"Disables the lookup of cluster scope resources (incompatible with IngressClasses and NodePortLB enabled services)." json:"disableClusterScopeResources,omitempty" toml:"disableClusterScopeResources,omitempty" yaml:"disableClusterScopeResources,omitempty" export:"true"`
|
||||||
NativeLBByDefault bool `description:"Defines whether to use Native Kubernetes load-balancing mode by default." json:"nativeLBByDefault,omitempty" toml:"nativeLBByDefault,omitempty" yaml:"nativeLBByDefault,omitempty" export:"true"`
|
NativeLBByDefault bool `description:"Defines whether to use Native Kubernetes load-balancing mode by default." json:"nativeLBByDefault,omitempty" toml:"nativeLBByDefault,omitempty" yaml:"nativeLBByDefault,omitempty" export:"true"`
|
||||||
|
|
||||||
|
// The default rule syntax is initialized with the configuration defined by the user with the core.DefaultRuleSyntax option.
|
||||||
|
DefaultRuleSyntax string `json:"-" toml:"-" yaml:"-" label:"-" file:"-"`
|
||||||
|
|
||||||
lastConfiguration safe.Safe
|
lastConfiguration safe.Safe
|
||||||
|
|
||||||
routerTransform k8s.RouterTransform
|
routerTransform k8s.RouterTransform
|
||||||
|
@ -336,7 +339,7 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
|
||||||
serviceName := provider.Normalize(ingress.Namespace + "-" + pa.Backend.Service.Name + "-" + portString)
|
serviceName := provider.Normalize(ingress.Namespace + "-" + pa.Backend.Service.Name + "-" + portString)
|
||||||
conf.HTTP.Services[serviceName] = service
|
conf.HTTP.Services[serviceName] = service
|
||||||
|
|
||||||
rt := loadRouter(rule, pa, rtConfig, serviceName)
|
rt := p.loadRouter(rule, pa, rtConfig, serviceName)
|
||||||
|
|
||||||
p.applyRouterTransform(ctxIngress, rt, ingress)
|
p.applyRouterTransform(ctxIngress, rt, ingress)
|
||||||
|
|
||||||
|
@ -432,100 +435,6 @@ func (p *Provider) shouldProcessIngress(ingress *netv1.Ingress, ingressClasses [
|
||||||
len(p.IngressClass) == 0 && ingress.Annotations[annotationKubernetesIngressClass] == traefikDefaultIngressClass
|
len(p.IngressClass) == 0 && ingress.Annotations[annotationKubernetesIngressClass] == traefikDefaultIngressClass
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildHostRule(host string) string {
|
|
||||||
if strings.HasPrefix(host, "*.") {
|
|
||||||
host = strings.Replace(regexp.QuoteMeta(host), `\*\.`, `[a-zA-Z0-9-]+\.`, 1)
|
|
||||||
return fmt.Sprintf("HostRegexp(`^%s$`)", host)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("Host(`%s`)", host)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCertificates(ctx context.Context, ingress *netv1.Ingress, k8sClient Client, tlsConfigs map[string]*tls.CertAndStores) error {
|
|
||||||
for _, t := range ingress.Spec.TLS {
|
|
||||||
if t.SecretName == "" {
|
|
||||||
log.Ctx(ctx).Debug().Msg("Skipping TLS sub-section: No secret name provided")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
configKey := ingress.Namespace + "-" + t.SecretName
|
|
||||||
if _, tlsExists := tlsConfigs[configKey]; !tlsExists {
|
|
||||||
secret, exists, err := k8sClient.GetSecret(ingress.Namespace, t.SecretName)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to fetch secret %s/%s: %w", ingress.Namespace, t.SecretName, err)
|
|
||||||
}
|
|
||||||
if !exists {
|
|
||||||
return fmt.Errorf("secret %s/%s does not exist", ingress.Namespace, t.SecretName)
|
|
||||||
}
|
|
||||||
|
|
||||||
cert, key, err := getCertificateBlocks(secret, ingress.Namespace, t.SecretName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsConfigs[configKey] = &tls.CertAndStores{
|
|
||||||
Certificate: tls.Certificate{
|
|
||||||
CertFile: types.FileOrContent(cert),
|
|
||||||
KeyFile: types.FileOrContent(key),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCertificateBlocks(secret *corev1.Secret, namespace, secretName string) (string, string, error) {
|
|
||||||
var missingEntries []string
|
|
||||||
|
|
||||||
tlsCrtData, tlsCrtExists := secret.Data["tls.crt"]
|
|
||||||
if !tlsCrtExists {
|
|
||||||
missingEntries = append(missingEntries, "tls.crt")
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsKeyData, tlsKeyExists := secret.Data["tls.key"]
|
|
||||||
if !tlsKeyExists {
|
|
||||||
missingEntries = append(missingEntries, "tls.key")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(missingEntries) > 0 {
|
|
||||||
return "", "", fmt.Errorf("secret %s/%s is missing the following TLS data entries: %s",
|
|
||||||
namespace, secretName, strings.Join(missingEntries, ", "))
|
|
||||||
}
|
|
||||||
|
|
||||||
cert := string(tlsCrtData)
|
|
||||||
if cert == "" {
|
|
||||||
missingEntries = append(missingEntries, "tls.crt")
|
|
||||||
}
|
|
||||||
|
|
||||||
key := string(tlsKeyData)
|
|
||||||
if key == "" {
|
|
||||||
missingEntries = append(missingEntries, "tls.key")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(missingEntries) > 0 {
|
|
||||||
return "", "", fmt.Errorf("secret %s/%s contains the following empty TLS data entries: %s",
|
|
||||||
namespace, secretName, strings.Join(missingEntries, ", "))
|
|
||||||
}
|
|
||||||
|
|
||||||
return cert, key, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTLSConfig(tlsConfigs map[string]*tls.CertAndStores) []*tls.CertAndStores {
|
|
||||||
var secretNames []string
|
|
||||||
for secretName := range tlsConfigs {
|
|
||||||
secretNames = append(secretNames, secretName)
|
|
||||||
}
|
|
||||||
sort.Strings(secretNames)
|
|
||||||
|
|
||||||
var configs []*tls.CertAndStores
|
|
||||||
for _, secretName := range secretNames {
|
|
||||||
configs = append(configs, tlsConfigs[secretName])
|
|
||||||
}
|
|
||||||
|
|
||||||
return configs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Provider) loadService(client Client, namespace string, backend netv1.IngressBackend) (*dynamic.Service, error) {
|
func (p *Provider) loadService(client Client, namespace string, backend netv1.IngressBackend) (*dynamic.Service, error) {
|
||||||
if backend.Resource != nil {
|
if backend.Resource != nil {
|
||||||
// https://kubernetes.io/docs/concepts/services-networking/ingress/#resource-backend
|
// https://kubernetes.io/docs/concepts/services-networking/ingress/#resource-backend
|
||||||
|
@ -698,6 +607,152 @@ func (p *Provider) loadService(client Client, namespace string, backend netv1.In
|
||||||
return svc, nil
|
return svc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) loadRouter(rule netv1.IngressRule, pa netv1.HTTPIngressPath, rtConfig *RouterConfig, serviceName string) *dynamic.Router {
|
||||||
|
rt := &dynamic.Router{
|
||||||
|
Service: serviceName,
|
||||||
|
}
|
||||||
|
|
||||||
|
if rtConfig != nil && rtConfig.Router != nil {
|
||||||
|
rt.RuleSyntax = rtConfig.Router.RuleSyntax
|
||||||
|
rt.Priority = rtConfig.Router.Priority
|
||||||
|
rt.EntryPoints = rtConfig.Router.EntryPoints
|
||||||
|
rt.Middlewares = rtConfig.Router.Middlewares
|
||||||
|
|
||||||
|
if rtConfig.Router.TLS != nil {
|
||||||
|
rt.TLS = rtConfig.Router.TLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rules []string
|
||||||
|
if len(rule.Host) > 0 {
|
||||||
|
if rt.RuleSyntax == "v2" || (rt.RuleSyntax == "" && p.DefaultRuleSyntax == "v2") {
|
||||||
|
rules = append(rules, buildHostRuleV2(rule.Host))
|
||||||
|
} else {
|
||||||
|
rules = append(rules, buildHostRule(rule.Host))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(pa.Path) > 0 {
|
||||||
|
matcher := defaultPathMatcher
|
||||||
|
|
||||||
|
if pa.PathType == nil || *pa.PathType == "" || *pa.PathType == netv1.PathTypeImplementationSpecific {
|
||||||
|
if rtConfig != nil && rtConfig.Router != nil && rtConfig.Router.PathMatcher != "" {
|
||||||
|
matcher = rtConfig.Router.PathMatcher
|
||||||
|
}
|
||||||
|
} else if *pa.PathType == netv1.PathTypeExact {
|
||||||
|
matcher = "Path"
|
||||||
|
}
|
||||||
|
|
||||||
|
rules = append(rules, fmt.Sprintf("%s(`%s`)", matcher, pa.Path))
|
||||||
|
}
|
||||||
|
|
||||||
|
rt.Rule = strings.Join(rules, " && ")
|
||||||
|
return rt
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildHostRuleV2(host string) string {
|
||||||
|
if strings.HasPrefix(host, "*.") {
|
||||||
|
host = strings.Replace(host, "*.", "{subdomain:[a-zA-Z0-9-]+}.", 1)
|
||||||
|
return fmt.Sprintf("HostRegexp(`%s`)", host)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("Host(`%s`)", host)
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildHostRule(host string) string {
|
||||||
|
if strings.HasPrefix(host, "*.") {
|
||||||
|
host = strings.Replace(regexp.QuoteMeta(host), `\*\.`, `[a-zA-Z0-9-]+\.`, 1)
|
||||||
|
return fmt.Sprintf("HostRegexp(`^%s$`)", host)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("Host(`%s`)", host)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCertificates(ctx context.Context, ingress *netv1.Ingress, k8sClient Client, tlsConfigs map[string]*tls.CertAndStores) error {
|
||||||
|
for _, t := range ingress.Spec.TLS {
|
||||||
|
if t.SecretName == "" {
|
||||||
|
log.Ctx(ctx).Debug().Msg("Skipping TLS sub-section: No secret name provided")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
configKey := ingress.Namespace + "-" + t.SecretName
|
||||||
|
if _, tlsExists := tlsConfigs[configKey]; !tlsExists {
|
||||||
|
secret, exists, err := k8sClient.GetSecret(ingress.Namespace, t.SecretName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to fetch secret %s/%s: %w", ingress.Namespace, t.SecretName, err)
|
||||||
|
}
|
||||||
|
if !exists {
|
||||||
|
return fmt.Errorf("secret %s/%s does not exist", ingress.Namespace, t.SecretName)
|
||||||
|
}
|
||||||
|
|
||||||
|
cert, key, err := getCertificateBlocks(secret, ingress.Namespace, t.SecretName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConfigs[configKey] = &tls.CertAndStores{
|
||||||
|
Certificate: tls.Certificate{
|
||||||
|
CertFile: types.FileOrContent(cert),
|
||||||
|
KeyFile: types.FileOrContent(key),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCertificateBlocks(secret *corev1.Secret, namespace, secretName string) (string, string, error) {
|
||||||
|
var missingEntries []string
|
||||||
|
|
||||||
|
tlsCrtData, tlsCrtExists := secret.Data["tls.crt"]
|
||||||
|
if !tlsCrtExists {
|
||||||
|
missingEntries = append(missingEntries, "tls.crt")
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsKeyData, tlsKeyExists := secret.Data["tls.key"]
|
||||||
|
if !tlsKeyExists {
|
||||||
|
missingEntries = append(missingEntries, "tls.key")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(missingEntries) > 0 {
|
||||||
|
return "", "", fmt.Errorf("secret %s/%s is missing the following TLS data entries: %s",
|
||||||
|
namespace, secretName, strings.Join(missingEntries, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
cert := string(tlsCrtData)
|
||||||
|
if cert == "" {
|
||||||
|
missingEntries = append(missingEntries, "tls.crt")
|
||||||
|
}
|
||||||
|
|
||||||
|
key := string(tlsKeyData)
|
||||||
|
if key == "" {
|
||||||
|
missingEntries = append(missingEntries, "tls.key")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(missingEntries) > 0 {
|
||||||
|
return "", "", fmt.Errorf("secret %s/%s contains the following empty TLS data entries: %s",
|
||||||
|
namespace, secretName, strings.Join(missingEntries, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
return cert, key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTLSConfig(tlsConfigs map[string]*tls.CertAndStores) []*tls.CertAndStores {
|
||||||
|
var secretNames []string
|
||||||
|
for secretName := range tlsConfigs {
|
||||||
|
secretNames = append(secretNames, secretName)
|
||||||
|
}
|
||||||
|
sort.Strings(secretNames)
|
||||||
|
|
||||||
|
var configs []*tls.CertAndStores
|
||||||
|
for _, secretName := range secretNames {
|
||||||
|
configs = append(configs, tlsConfigs[secretName])
|
||||||
|
}
|
||||||
|
|
||||||
|
return configs
|
||||||
|
}
|
||||||
|
|
||||||
func getNativeServiceAddress(service corev1.Service, svcPort corev1.ServicePort) (string, error) {
|
func getNativeServiceAddress(service corev1.Service, svcPort corev1.ServicePort) (string, error) {
|
||||||
if service.Spec.ClusterIP == "None" {
|
if service.Spec.ClusterIP == "None" {
|
||||||
return "", fmt.Errorf("no clusterIP on headless service: %s/%s", service.Namespace, service.Name)
|
return "", fmt.Errorf("no clusterIP on headless service: %s/%s", service.Namespace, service.Name)
|
||||||
|
@ -734,45 +789,6 @@ func makeRouterKeyWithHash(key, rule string) (string, error) {
|
||||||
return dupKey, nil
|
return dupKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadRouter(rule netv1.IngressRule, pa netv1.HTTPIngressPath, rtConfig *RouterConfig, serviceName string) *dynamic.Router {
|
|
||||||
var rules []string
|
|
||||||
if len(rule.Host) > 0 {
|
|
||||||
rules = []string{buildHostRule(rule.Host)}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(pa.Path) > 0 {
|
|
||||||
matcher := defaultPathMatcher
|
|
||||||
|
|
||||||
if pa.PathType == nil || *pa.PathType == "" || *pa.PathType == netv1.PathTypeImplementationSpecific {
|
|
||||||
if rtConfig != nil && rtConfig.Router != nil && rtConfig.Router.PathMatcher != "" {
|
|
||||||
matcher = rtConfig.Router.PathMatcher
|
|
||||||
}
|
|
||||||
} else if *pa.PathType == netv1.PathTypeExact {
|
|
||||||
matcher = "Path"
|
|
||||||
}
|
|
||||||
|
|
||||||
rules = append(rules, fmt.Sprintf("%s(`%s`)", matcher, pa.Path))
|
|
||||||
}
|
|
||||||
|
|
||||||
rt := &dynamic.Router{
|
|
||||||
Rule: strings.Join(rules, " && "),
|
|
||||||
Service: serviceName,
|
|
||||||
}
|
|
||||||
|
|
||||||
if rtConfig != nil && rtConfig.Router != nil {
|
|
||||||
rt.RuleSyntax = rtConfig.Router.RuleSyntax
|
|
||||||
rt.Priority = rtConfig.Router.Priority
|
|
||||||
rt.EntryPoints = rtConfig.Router.EntryPoints
|
|
||||||
rt.Middlewares = rtConfig.Router.Middlewares
|
|
||||||
|
|
||||||
if rtConfig.Router.TLS != nil {
|
|
||||||
rt.TLS = rtConfig.Router.TLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rt
|
|
||||||
}
|
|
||||||
|
|
||||||
func throttleEvents(ctx context.Context, throttleDuration time.Duration, pool *safe.Pool, eventsChan <-chan interface{}) chan interface{} {
|
func throttleEvents(ctx context.Context, throttleDuration time.Duration, pool *safe.Pool, eventsChan <-chan interface{}) chan interface{} {
|
||||||
if throttleDuration == 0 {
|
if throttleDuration == 0 {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
|
|
||||||
var _ provider.Provider = (*Provider)(nil)
|
var _ provider.Provider = (*Provider)(nil)
|
||||||
|
|
||||||
func Bool(v bool) *bool { return &v }
|
func pointer[T any](v T) *T { return &v }
|
||||||
|
|
||||||
func String(v string) *string { return &v }
|
func String(v string) *string { return &v }
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
allowEmptyServices bool
|
allowEmptyServices bool
|
||||||
disableIngressClassLookup bool
|
disableIngressClassLookup bool
|
||||||
disableClusterScopeResources bool
|
disableClusterScopeResources bool
|
||||||
|
defaultRuleSyntax string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "Empty ingresses",
|
desc: "Empty ingresses",
|
||||||
|
@ -69,7 +70,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -119,7 +120,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -164,7 +165,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -200,7 +201,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -236,7 +237,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -272,7 +273,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -304,7 +305,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -336,7 +337,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-example-com-80": {
|
"testing-example-com-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -369,7 +370,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -405,7 +406,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -441,7 +442,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -457,7 +458,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
"testing-service2-8082": {
|
"testing-service2-8082": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -490,7 +491,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -526,7 +527,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default-backend": {
|
"default-backend": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -558,7 +559,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -590,7 +591,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-tchouk": {
|
"testing-service1-tchouk": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -622,7 +623,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-tchouk": {
|
"testing-service1-tchouk": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -658,7 +659,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-tchouk": {
|
"testing-service1-tchouk": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -674,7 +675,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
"testing-service1-carotte": {
|
"testing-service1-carotte": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -706,7 +707,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-tchouk": {
|
"testing-service1-tchouk": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -742,7 +743,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-tchouk": {
|
"testing-service1-tchouk": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -758,7 +759,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
"toto-service1-tchouk": {
|
"toto-service1-tchouk": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -810,7 +811,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-8080": {
|
"testing-service1-8080": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -840,7 +841,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-example-com-80": {
|
"testing-example-com-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -879,7 +880,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-443": {
|
"testing-service1-443": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -911,7 +912,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-8443": {
|
"testing-service1-8443": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -944,7 +945,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-8443": {
|
"testing-service1-8443": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -978,7 +979,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default-backend": {
|
"default-backend": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1010,7 +1011,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1082,7 +1083,39 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
|
},
|
||||||
|
Servers: []dynamic.Server{
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.1:8080",
|
||||||
|
Scheme: "",
|
||||||
|
Port: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Ingress with wildcard host syntax v2",
|
||||||
|
defaultRuleSyntax: "v2",
|
||||||
|
expected: &dynamic.Configuration{
|
||||||
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
|
Routers: map[string]*dynamic.Router{
|
||||||
|
"testing-foobar-com-bar": {
|
||||||
|
Rule: "HostRegexp(`{subdomain:[a-zA-Z0-9-]+}.foobar.com`) && PathPrefix(`/bar`)",
|
||||||
|
Service: "testing-service1-80",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Services: map[string]*dynamic.Service{
|
||||||
|
"testing-service1-80": {
|
||||||
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1117,7 +1150,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1147,7 +1180,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1176,7 +1209,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1205,7 +1238,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1234,7 +1267,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1263,7 +1296,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1292,7 +1325,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1324,7 +1357,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1356,7 +1389,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1385,7 +1418,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-80": {
|
"testing-service1-80": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1440,7 +1473,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-foobar": {
|
"testing-service1-foobar": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1481,7 +1514,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"default-backend": {
|
"default-backend": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1508,6 +1541,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
AllowEmptyServices: test.allowEmptyServices,
|
AllowEmptyServices: test.allowEmptyServices,
|
||||||
DisableIngressClassLookup: test.disableIngressClassLookup,
|
DisableIngressClassLookup: test.disableIngressClassLookup,
|
||||||
DisableClusterScopeResources: test.disableClusterScopeResources,
|
DisableClusterScopeResources: test.disableClusterScopeResources,
|
||||||
|
DefaultRuleSyntax: test.defaultRuleSyntax,
|
||||||
}
|
}
|
||||||
conf := p.loadConfigurationFromIngresses(context.Background(), clientMock)
|
conf := p.loadConfigurationFromIngresses(context.Background(), clientMock)
|
||||||
|
|
||||||
|
@ -1548,7 +1582,7 @@ func TestLoadConfigurationFromIngressesWithExternalNameServices(t *testing.T) {
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
"testing-service1-8080": {
|
"testing-service1-8080": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1582,7 +1616,7 @@ func TestLoadConfigurationFromIngressesWithExternalNameServices(t *testing.T) {
|
||||||
URL: "http://[2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b]:8080",
|
URL: "http://[2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b]:8080",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1612,7 +1646,7 @@ func TestLoadConfigurationFromIngressesWithExternalNameServices(t *testing.T) {
|
||||||
URL: "http://[2001:0db8:3c4d:0015:0000:0000:1a2f:2a3b]:8080",
|
URL: "http://[2001:0db8:3c4d:0015:0000:0000:1a2f:2a3b]:8080",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1660,7 +1694,7 @@ func TestLoadConfigurationFromIngressesWithNativeLB(t *testing.T) {
|
||||||
"testing-service1-8080": {
|
"testing-service1-8080": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{FlushInterval: dynamic.DefaultFlushInterval},
|
ResponseForwarding: &dynamic.ResponseForwarding{FlushInterval: dynamic.DefaultFlushInterval},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://10.0.0.1:8080",
|
URL: "http://10.0.0.1:8080",
|
||||||
|
@ -1709,7 +1743,7 @@ func TestLoadConfigurationFromIngressesWithNodePortLB(t *testing.T) {
|
||||||
"testing-service1-8080": {
|
"testing-service1-8080": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{FlushInterval: dynamic.DefaultFlushInterval},
|
ResponseForwarding: &dynamic.ResponseForwarding{FlushInterval: dynamic.DefaultFlushInterval},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://172.16.4.4:32456",
|
URL: "http://172.16.4.4:32456",
|
||||||
|
@ -1946,7 +1980,7 @@ func TestLoadConfigurationFromIngressesWithNativeLBByDefault(t *testing.T) {
|
||||||
"testing-service1-8080": {
|
"testing-service1-8080": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{FlushInterval: dynamic.DefaultFlushInterval},
|
ResponseForwarding: &dynamic.ResponseForwarding{FlushInterval: dynamic.DefaultFlushInterval},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://10.0.0.1:8080",
|
URL: "http://10.0.0.1:8080",
|
||||||
|
@ -1973,7 +2007,7 @@ func TestLoadConfigurationFromIngressesWithNativeLBByDefault(t *testing.T) {
|
||||||
"default-service1-8080": {
|
"default-service1-8080": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{FlushInterval: dynamic.DefaultFlushInterval},
|
ResponseForwarding: &dynamic.ResponseForwarding{FlushInterval: dynamic.DefaultFlushInterval},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: "http://10.0.0.1:8080",
|
URL: "http://10.0.0.1:8080",
|
||||||
|
|
|
@ -15,8 +15,7 @@ import (
|
||||||
"github.com/traefik/traefik/v3/pkg/types"
|
"github.com/traefik/traefik/v3/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Bool(v bool) *bool { return &v }
|
func pointer[T any](v T) *T { return &v }
|
||||||
func String(v string) *string { return &v }
|
|
||||||
|
|
||||||
func Test_buildConfiguration(t *testing.T) {
|
func Test_buildConfiguration(t *testing.T) {
|
||||||
provider := newProviderMock(mapToPairs(map[string]string{
|
provider := newProviderMock(mapToPairs(map[string]string{
|
||||||
|
@ -387,7 +386,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"foobar",
|
"foobar",
|
||||||
},
|
},
|
||||||
ForceSlash: Bool(true),
|
ForceSlash: pointer(true),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Middleware00": {
|
"Middleware00": {
|
||||||
|
@ -430,7 +429,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
Cert: "foobar",
|
Cert: "foobar",
|
||||||
Key: "foobar",
|
Key: "foobar",
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
CAOptional: Bool(true),
|
CAOptional: pointer(true),
|
||||||
},
|
},
|
||||||
TrustForwardHeader: true,
|
TrustForwardHeader: true,
|
||||||
AuthResponseHeaders: []string{
|
AuthResponseHeaders: []string{
|
||||||
|
@ -603,14 +602,14 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"foobar",
|
"foobar",
|
||||||
},
|
},
|
||||||
SSLRedirect: Bool(true),
|
SSLRedirect: pointer(true),
|
||||||
SSLTemporaryRedirect: Bool(true),
|
SSLTemporaryRedirect: pointer(true),
|
||||||
SSLHost: String("foobar"),
|
SSLHost: pointer("foobar"),
|
||||||
SSLProxyHeaders: map[string]string{
|
SSLProxyHeaders: map[string]string{
|
||||||
"name1": "foobar",
|
"name1": "foobar",
|
||||||
"name0": "foobar",
|
"name0": "foobar",
|
||||||
},
|
},
|
||||||
SSLForceHost: Bool(true),
|
SSLForceHost: pointer(true),
|
||||||
STSSeconds: 42,
|
STSSeconds: 42,
|
||||||
STSIncludeSubdomains: true,
|
STSIncludeSubdomains: true,
|
||||||
STSPreload: true,
|
STSPreload: true,
|
||||||
|
@ -624,7 +623,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
ContentSecurityPolicyReportOnly: "foobar",
|
ContentSecurityPolicyReportOnly: "foobar",
|
||||||
PublicKey: "foobar",
|
PublicKey: "foobar",
|
||||||
ReferrerPolicy: "foobar",
|
ReferrerPolicy: "foobar",
|
||||||
FeaturePolicy: String("foobar"),
|
FeaturePolicy: pointer("foobar"),
|
||||||
PermissionsPolicy: "foobar",
|
PermissionsPolicy: "foobar",
|
||||||
IsDevelopment: true,
|
IsDevelopment: true,
|
||||||
},
|
},
|
||||||
|
@ -665,13 +664,13 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
Interval: ptypes.Duration(time.Second),
|
Interval: ptypes.Duration(time.Second),
|
||||||
Timeout: ptypes.Duration(time.Second),
|
Timeout: ptypes.Duration(time.Second),
|
||||||
Hostname: "foobar",
|
Hostname: "foobar",
|
||||||
FollowRedirects: func(v bool) *bool { return &v }(true),
|
FollowRedirects: pointer(true),
|
||||||
Headers: map[string]string{
|
Headers: map[string]string{
|
||||||
"name0": "foobar",
|
"name0": "foobar",
|
||||||
"name1": "foobar",
|
"name1": "foobar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: func(v bool) *bool { return &v }(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(time.Second),
|
FlushInterval: ptypes.Duration(time.Second),
|
||||||
},
|
},
|
||||||
|
@ -680,8 +679,8 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
"Service02": {
|
"Service02": {
|
||||||
Mirroring: &dynamic.Mirroring{
|
Mirroring: &dynamic.Mirroring{
|
||||||
Service: "foobar",
|
Service: "foobar",
|
||||||
MirrorBody: func(v bool) *bool { return &v }(true),
|
MirrorBody: pointer(true),
|
||||||
MaxBodySize: func(v int64) *int64 { return &v }(42),
|
MaxBodySize: pointer[int64](42),
|
||||||
Mirrors: []dynamic.MirrorService{
|
Mirrors: []dynamic.MirrorService{
|
||||||
{
|
{
|
||||||
Name: "foobar",
|
Name: "foobar",
|
||||||
|
@ -699,11 +698,11 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
Services: []dynamic.WRRService{
|
Services: []dynamic.WRRService{
|
||||||
{
|
{
|
||||||
Name: "foobar",
|
Name: "foobar",
|
||||||
Weight: func(v int) *int { return &v }(42),
|
Weight: pointer(42),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "foobar",
|
Name: "foobar",
|
||||||
Weight: func(v int) *int { return &v }(42),
|
Weight: pointer(42),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Sticky: &dynamic.Sticky{
|
Sticky: &dynamic.Sticky{
|
||||||
|
@ -788,7 +787,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"TCPService01": {
|
"TCPService01": {
|
||||||
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
TerminationDelay: func(v int) *int { return &v }(42),
|
TerminationDelay: pointer(42),
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{Address: "foobar"},
|
{Address: "foobar"},
|
||||||
{Address: "foobar"},
|
{Address: "foobar"},
|
||||||
|
@ -800,11 +799,11 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
Services: []dynamic.TCPWRRService{
|
Services: []dynamic.TCPWRRService{
|
||||||
{
|
{
|
||||||
Name: "foobar",
|
Name: "foobar",
|
||||||
Weight: func(v int) *int { return &v }(42),
|
Weight: pointer(42),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "foobar",
|
Name: "foobar",
|
||||||
Weight: func(v int) *int { return &v }(43),
|
Weight: pointer(43),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -61,7 +61,7 @@ func Test_defaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -119,7 +119,7 @@ func Test_defaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -168,7 +168,7 @@ func Test_defaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -223,7 +223,7 @@ func Test_defaultRule(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -301,7 +301,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -368,7 +368,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://192.168.1.101:9999",
|
URL: "http://192.168.1.101:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -381,7 +381,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://192.168.1.102:9999",
|
URL: "http://192.168.1.102:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -448,7 +448,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:9999",
|
URL: "http://127.0.0.2:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -512,7 +512,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:9999",
|
URL: "http://127.0.0.2:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -579,7 +579,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:9999",
|
URL: "http://127.0.0.2:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -635,7 +635,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -692,7 +692,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -777,7 +777,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -839,7 +839,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -891,7 +891,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -904,7 +904,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1087,7 +1087,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:9999",
|
URL: "http://127.0.0.2:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1142,7 +1142,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1224,7 +1224,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:9999",
|
URL: "http://127.0.0.2:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1293,7 +1293,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:9999",
|
URL: "http://127.0.0.2:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1356,7 +1356,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:9999",
|
URL: "http://127.0.0.2:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1424,7 +1424,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:9999",
|
URL: "http://127.0.0.2:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1480,7 +1480,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1537,7 +1537,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "h2c://127.0.0.1:8080",
|
URL: "h2c://127.0.0.1:8080",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1588,7 +1588,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1601,7 +1601,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:8080",
|
URL: "http://127.0.0.1:8080",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1800,7 +1800,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -1867,7 +1867,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2279,7 +2279,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:9999",
|
URL: "http://127.0.0.2:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2370,7 +2370,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:9999",
|
URL: "http://127.0.0.2:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2587,7 +2587,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:80",
|
URL: "http://127.0.0.1:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2600,7 +2600,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.2:80",
|
URL: "http://127.0.0.2:80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2819,7 +2819,7 @@ func Test_buildConfig(t *testing.T) {
|
||||||
URL: "http://127.0.0.1:9999",
|
URL: "http://127.0.0.1:9999",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -2906,7 +2906,7 @@ func Test_buildConfigAllowEmptyServicesTrue(t *testing.T) {
|
||||||
"Test": {
|
"Test": {
|
||||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
Servers: nil,
|
Servers: nil,
|
||||||
PassHostHeader: Bool(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
},
|
},
|
||||||
|
@ -3254,5 +3254,4 @@ func extractNamespacesFromProvider(providers []*Provider) []string {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func Int(v int) *int { return &v }
|
func pointer[T any](v T) *T { return &v }
|
||||||
func Bool(v bool) *bool { return &v }
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ func New(staticCfg static.Configuration) *Provider {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ThrottleDuration returns the throttle duration.
|
// ThrottleDuration returns the throttle duration.
|
||||||
func (i Provider) ThrottleDuration() time.Duration {
|
func (i *Provider) ThrottleDuration() time.Duration {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -171,7 +171,7 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
if reqUpType != "" {
|
if reqUpType != "" {
|
||||||
outReq.Header.Set("Connection", "Upgrade")
|
outReq.Header.Set("Connection", "Upgrade")
|
||||||
outReq.Header.Set("Upgrade", reqUpType)
|
outReq.Header.Set("Upgrade", reqUpType)
|
||||||
if reqUpType == "websocket" {
|
if strings.EqualFold(reqUpType, "websocket") {
|
||||||
cleanWebSocketHeaders(&outReq.Header)
|
cleanWebSocketHeaders(&outReq.Header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -353,6 +353,7 @@ type fasthttpHeader interface {
|
||||||
SetBytesV(key string, value []byte)
|
SetBytesV(key string, value []byte)
|
||||||
DelBytes(key []byte)
|
DelBytes(key []byte)
|
||||||
Del(key string)
|
Del(key string)
|
||||||
|
ConnectionUpgrade() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// removeConnectionHeaders removes hop-by-hop headers listed in the "Connection" header of h.
|
// removeConnectionHeaders removes hop-by-hop headers listed in the "Connection" header of h.
|
||||||
|
|
|
@ -2,7 +2,9 @@ package fast
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"crypto/sha1"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
@ -19,6 +21,34 @@ import (
|
||||||
"golang.org/x/net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestWebSocketUpgradeCase(t *testing.T) {
|
||||||
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
challengeKey := r.Header.Get("Sec-Websocket-Key")
|
||||||
|
|
||||||
|
hijacker, ok := w.(http.Hijacker)
|
||||||
|
require.True(t, ok)
|
||||||
|
|
||||||
|
c, _, err := hijacker.Hijack()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Force answer with "Connection: upgrade" in lowercase.
|
||||||
|
_, err = c.Write([]byte("HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: upgrade\r\nSec-WebSocket-Accept: " + computeAcceptKey(challengeKey) + "\r\n\n"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
}))
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
proxy := createProxyWithForwarder(t, srv.URL, createConnectionPool(srv.URL, nil))
|
||||||
|
|
||||||
|
proxyAddr := proxy.Listener.Addr().String()
|
||||||
|
_, conn, err := newWebsocketRequest(
|
||||||
|
withServer(proxyAddr),
|
||||||
|
withPath("/ws"),
|
||||||
|
).open()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
func TestWebSocketTCPClose(t *testing.T) {
|
func TestWebSocketTCPClose(t *testing.T) {
|
||||||
errChan := make(chan error, 1)
|
errChan := make(chan error, 1)
|
||||||
upgrader := gorillawebsocket.Upgrader{}
|
upgrader := gorillawebsocket.Upgrader{}
|
||||||
|
@ -691,3 +721,10 @@ func createProxyWithForwarder(t *testing.T, uri string, pool *connPool) *httptes
|
||||||
|
|
||||||
return srv
|
return srv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func computeAcceptKey(challengeKey string) string {
|
||||||
|
h := sha1.New() // #nosec G401 -- (CWE-326) https://datatracker.ietf.org/doc/html/rfc6455#page-54
|
||||||
|
h.Write([]byte(challengeKey))
|
||||||
|
h.Write([]byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))
|
||||||
|
return base64.StdEncoding.EncodeToString(h.Sum(nil))
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package fast
|
package fast
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -100,7 +99,7 @@ func upgradeType(h http.Header) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func upgradeTypeFastHTTP(h fasthttpHeader) string {
|
func upgradeTypeFastHTTP(h fasthttpHeader) string {
|
||||||
if !bytes.Contains(h.Peek("Connection"), []byte("Upgrade")) {
|
if !h.ConnectionUpgrade() {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,12 +78,12 @@ func init() {
|
||||||
Interval: ptypes.Duration(111 * time.Second),
|
Interval: ptypes.Duration(111 * time.Second),
|
||||||
Timeout: ptypes.Duration(111 * time.Second),
|
Timeout: ptypes.Duration(111 * time.Second),
|
||||||
Hostname: "foo",
|
Hostname: "foo",
|
||||||
FollowRedirects: boolPtr(true),
|
FollowRedirects: pointer(true),
|
||||||
Headers: map[string]string{
|
Headers: map[string]string{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
PassHostHeader: boolPtr(true),
|
PassHostHeader: pointer(true),
|
||||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
FlushInterval: ptypes.Duration(111 * time.Second),
|
FlushInterval: ptypes.Duration(111 * time.Second),
|
||||||
},
|
},
|
||||||
|
@ -100,7 +100,7 @@ func init() {
|
||||||
Services: []dynamic.WRRService{
|
Services: []dynamic.WRRService{
|
||||||
{
|
{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Weight: intPtr(42),
|
Weight: pointer(42),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Sticky: &dynamic.Sticky{
|
Sticky: &dynamic.Sticky{
|
||||||
|
@ -116,7 +116,7 @@ func init() {
|
||||||
"baz": {
|
"baz": {
|
||||||
Mirroring: &dynamic.Mirroring{
|
Mirroring: &dynamic.Mirroring{
|
||||||
Service: "foo",
|
Service: "foo",
|
||||||
MaxBodySize: int64Ptr(42),
|
MaxBodySize: pointer[int64](42),
|
||||||
Mirrors: []dynamic.MirrorService{
|
Mirrors: []dynamic.MirrorService{
|
||||||
{
|
{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
|
@ -380,7 +380,7 @@ func init() {
|
||||||
Services: []dynamic.TCPWRRService{
|
Services: []dynamic.TCPWRRService{
|
||||||
{
|
{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Weight: intPtr(42),
|
Weight: pointer(42),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -427,7 +427,7 @@ func init() {
|
||||||
Services: []dynamic.UDPWRRService{
|
Services: []dynamic.UDPWRRService{
|
||||||
{
|
{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Weight: intPtr(42),
|
Weight: pointer(42),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -484,7 +484,7 @@ func TestAnonymize_dynamicConfiguration(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := strings.TrimSuffix(string(expectedConfiguration), "\n")
|
expected := strings.TrimSuffix(string(expectedConfiguration), "\n")
|
||||||
assert.Equal(t, expected, cleanJSON)
|
assert.JSONEq(t, expected, cleanJSON)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSecure_dynamicConfiguration(t *testing.T) {
|
func TestSecure_dynamicConfiguration(t *testing.T) {
|
||||||
|
@ -501,7 +501,7 @@ func TestSecure_dynamicConfiguration(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := strings.TrimSuffix(string(expectedConfiguration), "\n")
|
expected := strings.TrimSuffix(string(expectedConfiguration), "\n")
|
||||||
assert.Equal(t, expected, cleanJSON)
|
assert.JSONEq(t, expected, cleanJSON)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDo_staticConfiguration(t *testing.T) {
|
func TestDo_staticConfiguration(t *testing.T) {
|
||||||
|
@ -950,17 +950,7 @@ func TestDo_staticConfiguration(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := strings.TrimSuffix(string(expectedConfiguration), "\n")
|
expected := strings.TrimSuffix(string(expectedConfiguration), "\n")
|
||||||
assert.Equal(t, expected, cleanJSON)
|
assert.JSONEq(t, expected, cleanJSON)
|
||||||
}
|
}
|
||||||
|
|
||||||
func boolPtr(value bool) *bool {
|
func pointer[T any](v T) *T { return &v }
|
||||||
return &value
|
|
||||||
}
|
|
||||||
|
|
||||||
func intPtr(value int) *int {
|
|
||||||
return &value
|
|
||||||
}
|
|
||||||
|
|
||||||
func int64Ptr(value int64) *int64 {
|
|
||||||
return &value
|
|
||||||
}
|
|
||||||
|
|
|
@ -323,7 +323,7 @@ func TestListenProvidersThrottleProviderConfigReload(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
providerAggregator := aggregator.ProviderAggregator{}
|
providerAggregator := &aggregator.ProviderAggregator{}
|
||||||
err := providerAggregator.AddProvider(pvd)
|
err := providerAggregator.AddProvider(pvd)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
@ -507,7 +507,7 @@ func TestListenProvidersIgnoreSameConfig(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
providerAggregator := aggregator.ProviderAggregator{}
|
providerAggregator := &aggregator.ProviderAggregator{}
|
||||||
err := providerAggregator.AddProvider(pvd)
|
err := providerAggregator.AddProvider(pvd)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
@ -651,7 +651,7 @@ func TestListenProvidersIgnoreIntermediateConfigs(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
providerAggregator := aggregator.ProviderAggregator{}
|
providerAggregator := &aggregator.ProviderAggregator{}
|
||||||
err := providerAggregator.AddProvider(pvd)
|
err := providerAggregator.AddProvider(pvd)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ func isPostgres(br *bufio.Reader) (bool, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var opErr *net.OpError
|
var opErr *net.OpError
|
||||||
if !errors.Is(err, io.EOF) && (!errors.As(err, &opErr) || !opErr.Timeout()) {
|
if !errors.Is(err, io.EOF) && (!errors.As(err, &opErr) || !opErr.Timeout()) {
|
||||||
log.Error().Err(err).Msg("Error while Peeking first byte")
|
log.Debug().Err(err).Msg("Error while peeking first bytes")
|
||||||
}
|
}
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -364,7 +364,7 @@ func clientHelloInfo(br *bufio.Reader) (*clientHello, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var opErr *net.OpError
|
var opErr *net.OpError
|
||||||
if !errors.Is(err, io.EOF) && (!errors.As(err, &opErr) || !opErr.Timeout()) {
|
if !errors.Is(err, io.EOF) && (!errors.As(err, &opErr) || !opErr.Timeout()) {
|
||||||
log.Error().Err(err).Msg("Error while Peeking first byte")
|
log.Debug().Err(err).Msg("Error while peeking first byte")
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -390,7 +390,7 @@ func clientHelloInfo(br *bufio.Reader) (*clientHello, error) {
|
||||||
const recordHeaderLen = 5
|
const recordHeaderLen = 5
|
||||||
hdr, err = br.Peek(recordHeaderLen)
|
hdr, err = br.Peek(recordHeaderLen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("Error while Peeking hello")
|
log.Error().Err(err).Msg("Error while peeking client hello header")
|
||||||
return &clientHello{
|
return &clientHello{
|
||||||
peeked: getPeeked(br),
|
peeked: getPeeked(br),
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -404,7 +404,7 @@ func clientHelloInfo(br *bufio.Reader) (*clientHello, error) {
|
||||||
|
|
||||||
helloBytes, err := br.Peek(recordHeaderLen + recLen)
|
helloBytes, err := br.Peek(recordHeaderLen + recLen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("Error while Hello")
|
log.Error().Err(err).Msg("Error while peeking client hello bytes")
|
||||||
return &clientHello{
|
return &clientHello{
|
||||||
isTLS: true,
|
isTLS: true,
|
||||||
peeked: getPeeked(br),
|
peeked: getPeeked(br),
|
||||||
|
@ -433,7 +433,7 @@ func clientHelloInfo(br *bufio.Reader) (*clientHello, error) {
|
||||||
func getPeeked(br *bufio.Reader) string {
|
func getPeeked(br *bufio.Reader) string {
|
||||||
peeked, err := br.Peek(br.Buffered())
|
peeked, err := br.Peek(br.Buffered())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("Could not get anything")
|
log.Error().Err(err).Msg("Error while peeking bytes")
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return string(peeked)
|
return string(peeked)
|
||||||
|
|
|
@ -625,17 +625,17 @@ func createHTTPServer(ctx context.Context, ln net.Listener, configuration *stati
|
||||||
|
|
||||||
handler = contenttype.DisableAutoDetection(handler)
|
handler = contenttype.DisableAutoDetection(handler)
|
||||||
|
|
||||||
|
debugConnection := os.Getenv(debugConnectionEnv) != ""
|
||||||
|
if debugConnection || (configuration.Transport != nil && (configuration.Transport.KeepAliveMaxTime > 0 || configuration.Transport.KeepAliveMaxRequests > 0)) {
|
||||||
|
handler = newKeepAliveMiddleware(handler, configuration.Transport.KeepAliveMaxRequests, configuration.Transport.KeepAliveMaxTime)
|
||||||
|
}
|
||||||
|
|
||||||
if withH2c {
|
if withH2c {
|
||||||
handler = h2c.NewHandler(handler, &http2.Server{
|
handler = h2c.NewHandler(handler, &http2.Server{
|
||||||
MaxConcurrentStreams: uint32(configuration.HTTP2.MaxConcurrentStreams),
|
MaxConcurrentStreams: uint32(configuration.HTTP2.MaxConcurrentStreams),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
debugConnection := os.Getenv(debugConnectionEnv) != ""
|
|
||||||
if debugConnection || (configuration.Transport != nil && (configuration.Transport.KeepAliveMaxTime > 0 || configuration.Transport.KeepAliveMaxRequests > 0)) {
|
|
||||||
handler = newKeepAliveMiddleware(handler, configuration.Transport.KeepAliveMaxRequests, configuration.Transport.KeepAliveMaxTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
serverHTTP := &http.Server{
|
serverHTTP := &http.Server{
|
||||||
Handler: handler,
|
Handler: handler,
|
||||||
ErrorLog: stdlog.New(logs.NoLevel(log.Logger, zerolog.DebugLevel), "", 0),
|
ErrorLog: stdlog.New(logs.NoLevel(log.Logger, zerolog.DebugLevel), "", 0),
|
||||||
|
|
|
@ -3,6 +3,7 @@ package server
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
@ -17,6 +18,7 @@ import (
|
||||||
"github.com/traefik/traefik/v3/pkg/config/static"
|
"github.com/traefik/traefik/v3/pkg/config/static"
|
||||||
tcprouter "github.com/traefik/traefik/v3/pkg/server/router/tcp"
|
tcprouter "github.com/traefik/traefik/v3/pkg/server/router/tcp"
|
||||||
"github.com/traefik/traefik/v3/pkg/tcp"
|
"github.com/traefik/traefik/v3/pkg/tcp"
|
||||||
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestShutdownHijacked(t *testing.T) {
|
func TestShutdownHijacked(t *testing.T) {
|
||||||
|
@ -330,3 +332,53 @@ func TestKeepAliveMaxTime(t *testing.T) {
|
||||||
err = resp.Body.Close()
|
err = resp.Body.Close()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestKeepAliveH2c(t *testing.T) {
|
||||||
|
epConfig := &static.EntryPointsTransport{}
|
||||||
|
epConfig.SetDefaults()
|
||||||
|
epConfig.KeepAliveMaxRequests = 1
|
||||||
|
|
||||||
|
entryPoint, err := NewTCPEntryPoint(context.Background(), "", &static.EntryPoint{
|
||||||
|
Address: ":0",
|
||||||
|
Transport: epConfig,
|
||||||
|
ForwardedHeaders: &static.ForwardedHeaders{},
|
||||||
|
HTTP2: &static.HTTP2Config{},
|
||||||
|
}, nil, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
router, err := tcprouter.NewRouter()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
router.SetHTTPHandler(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
rw.WriteHeader(http.StatusOK)
|
||||||
|
}))
|
||||||
|
|
||||||
|
conn, err := startEntrypoint(entryPoint, router)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
http2Transport := &http2.Transport{
|
||||||
|
AllowHTTP: true,
|
||||||
|
DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
|
||||||
|
return conn, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &http.Client{Transport: http2Transport}
|
||||||
|
|
||||||
|
resp, err := client.Get("http://" + entryPoint.listener.Addr().String())
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.False(t, resp.Close)
|
||||||
|
err = resp.Body.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = client.Get("http://" + entryPoint.listener.Addr().String())
|
||||||
|
require.Error(t, err)
|
||||||
|
// Unlike HTTP/1, where we can directly check `resp.Close`, HTTP/2 uses a different
|
||||||
|
// mechanism: it sends a GOAWAY frame when the connection is closing.
|
||||||
|
// We can only check the error type. The error received should be poll.ErrClosed from
|
||||||
|
// the `internal/poll` package, but we cannot directly reference the error type due to
|
||||||
|
// package restrictions. Since this error message ("use of closed network connection")
|
||||||
|
// is distinct and specific, we rely on its consistency, assuming it is stable and unlikely
|
||||||
|
// to change.
|
||||||
|
require.Contains(t, err.Error(), "use of closed network connection")
|
||||||
|
}
|
||||||
|
|
|
@ -8,11 +8,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type serviceManager interface {
|
|
||||||
BuildHTTP(rootCtx context.Context, serviceName string) (http.Handler, error)
|
|
||||||
LaunchHealthCheck(ctx context.Context)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InternalHandlers is the internal HTTP handlers builder.
|
// InternalHandlers is the internal HTTP handlers builder.
|
||||||
type InternalHandlers struct {
|
type InternalHandlers struct {
|
||||||
api http.Handler
|
api http.Handler
|
||||||
|
@ -21,11 +16,10 @@ type InternalHandlers struct {
|
||||||
prometheus http.Handler
|
prometheus http.Handler
|
||||||
ping http.Handler
|
ping http.Handler
|
||||||
acmeHTTP http.Handler
|
acmeHTTP http.Handler
|
||||||
serviceManager
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInternalHandlers creates a new InternalHandlers.
|
// NewInternalHandlers creates a new InternalHandlers.
|
||||||
func NewInternalHandlers(next serviceManager, apiHandler, rest, metricsHandler, pingHandler, dashboard, acmeHTTP http.Handler) *InternalHandlers {
|
func NewInternalHandlers(apiHandler, rest, metricsHandler, pingHandler, dashboard, acmeHTTP http.Handler) *InternalHandlers {
|
||||||
return &InternalHandlers{
|
return &InternalHandlers{
|
||||||
api: apiHandler,
|
api: apiHandler,
|
||||||
dashboard: dashboard,
|
dashboard: dashboard,
|
||||||
|
@ -33,14 +27,13 @@ func NewInternalHandlers(next serviceManager, apiHandler, rest, metricsHandler,
|
||||||
prometheus: metricsHandler,
|
prometheus: metricsHandler,
|
||||||
ping: pingHandler,
|
ping: pingHandler,
|
||||||
acmeHTTP: acmeHTTP,
|
acmeHTTP: acmeHTTP,
|
||||||
serviceManager: next,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildHTTP builds an HTTP handler.
|
// BuildHTTP builds an HTTP handler.
|
||||||
func (m *InternalHandlers) BuildHTTP(rootCtx context.Context, serviceName string) (http.Handler, error) {
|
func (m *InternalHandlers) BuildHTTP(rootCtx context.Context, serviceName string) (http.Handler, error) {
|
||||||
if !strings.HasSuffix(serviceName, "@internal") {
|
if !strings.HasSuffix(serviceName, "@internal") {
|
||||||
return m.serviceManager.BuildHTTP(rootCtx, serviceName)
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
internalHandler, err := m.get(serviceName)
|
internalHandler, err := m.get(serviceName)
|
||||||
|
|
|
@ -10,18 +10,20 @@ import (
|
||||||
"github.com/traefik/traefik/v3/pkg/config/dynamic"
|
"github.com/traefik/traefik/v3/pkg/config/dynamic"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func pointer[T any](v T) *T { return &v }
|
||||||
|
|
||||||
func TestBalancer(t *testing.T) {
|
func TestBalancer(t *testing.T) {
|
||||||
balancer := New(nil, false)
|
balancer := New(nil, false)
|
||||||
|
|
||||||
balancer.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("server", "first")
|
rw.Header().Set("server", "first")
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}), Int(3))
|
}), pointer(3))
|
||||||
|
|
||||||
balancer.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("server", "second")
|
rw.Header().Set("server", "second")
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}), Int(1))
|
}), pointer(1))
|
||||||
|
|
||||||
recorder := &responseRecorder{ResponseRecorder: httptest.NewRecorder(), save: map[string]int{}}
|
recorder := &responseRecorder{ResponseRecorder: httptest.NewRecorder(), save: map[string]int{}}
|
||||||
for range 4 {
|
for range 4 {
|
||||||
|
@ -47,9 +49,9 @@ func TestBalancerOneServerZeroWeight(t *testing.T) {
|
||||||
balancer.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("server", "first")
|
rw.Header().Set("server", "first")
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}), Int(1))
|
}), pointer(1))
|
||||||
|
|
||||||
balancer.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {}), Int(0))
|
balancer.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {}), pointer(0))
|
||||||
|
|
||||||
recorder := &responseRecorder{ResponseRecorder: httptest.NewRecorder(), save: map[string]int{}}
|
recorder := &responseRecorder{ResponseRecorder: httptest.NewRecorder(), save: map[string]int{}}
|
||||||
for range 3 {
|
for range 3 {
|
||||||
|
@ -68,11 +70,11 @@ func TestBalancerNoServiceUp(t *testing.T) {
|
||||||
|
|
||||||
balancer.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.WriteHeader(http.StatusInternalServerError)
|
rw.WriteHeader(http.StatusInternalServerError)
|
||||||
}), Int(1))
|
}), pointer(1))
|
||||||
|
|
||||||
balancer.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.WriteHeader(http.StatusInternalServerError)
|
rw.WriteHeader(http.StatusInternalServerError)
|
||||||
}), Int(1))
|
}), pointer(1))
|
||||||
|
|
||||||
balancer.SetStatus(context.WithValue(context.Background(), serviceName, "parent"), "first", false)
|
balancer.SetStatus(context.WithValue(context.Background(), serviceName, "parent"), "first", false)
|
||||||
balancer.SetStatus(context.WithValue(context.Background(), serviceName, "parent"), "second", false)
|
balancer.SetStatus(context.WithValue(context.Background(), serviceName, "parent"), "second", false)
|
||||||
|
@ -89,11 +91,11 @@ func TestBalancerOneServerDown(t *testing.T) {
|
||||||
balancer.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("server", "first")
|
rw.Header().Set("server", "first")
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}), Int(1))
|
}), pointer(1))
|
||||||
|
|
||||||
balancer.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.WriteHeader(http.StatusInternalServerError)
|
rw.WriteHeader(http.StatusInternalServerError)
|
||||||
}), Int(1))
|
}), pointer(1))
|
||||||
balancer.SetStatus(context.WithValue(context.Background(), serviceName, "parent"), "second", false)
|
balancer.SetStatus(context.WithValue(context.Background(), serviceName, "parent"), "second", false)
|
||||||
|
|
||||||
recorder := &responseRecorder{ResponseRecorder: httptest.NewRecorder(), save: map[string]int{}}
|
recorder := &responseRecorder{ResponseRecorder: httptest.NewRecorder(), save: map[string]int{}}
|
||||||
|
@ -110,12 +112,12 @@ func TestBalancerDownThenUp(t *testing.T) {
|
||||||
balancer.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("server", "first")
|
rw.Header().Set("server", "first")
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}), Int(1))
|
}), pointer(1))
|
||||||
|
|
||||||
balancer.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("server", "second")
|
rw.Header().Set("server", "second")
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}), Int(1))
|
}), pointer(1))
|
||||||
balancer.SetStatus(context.WithValue(context.Background(), serviceName, "parent"), "second", false)
|
balancer.SetStatus(context.WithValue(context.Background(), serviceName, "parent"), "second", false)
|
||||||
|
|
||||||
recorder := &responseRecorder{ResponseRecorder: httptest.NewRecorder(), save: map[string]int{}}
|
recorder := &responseRecorder{ResponseRecorder: httptest.NewRecorder(), save: map[string]int{}}
|
||||||
|
@ -139,30 +141,30 @@ func TestBalancerPropagate(t *testing.T) {
|
||||||
balancer1.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer1.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("server", "first")
|
rw.Header().Set("server", "first")
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}), Int(1))
|
}), pointer(1))
|
||||||
balancer1.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer1.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("server", "second")
|
rw.Header().Set("server", "second")
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}), Int(1))
|
}), pointer(1))
|
||||||
|
|
||||||
balancer2 := New(nil, true)
|
balancer2 := New(nil, true)
|
||||||
balancer2.Add("third", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer2.Add("third", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("server", "third")
|
rw.Header().Set("server", "third")
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}), Int(1))
|
}), pointer(1))
|
||||||
balancer2.Add("fourth", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer2.Add("fourth", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("server", "fourth")
|
rw.Header().Set("server", "fourth")
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}), Int(1))
|
}), pointer(1))
|
||||||
|
|
||||||
topBalancer := New(nil, true)
|
topBalancer := New(nil, true)
|
||||||
topBalancer.Add("balancer1", balancer1, Int(1))
|
topBalancer.Add("balancer1", balancer1, pointer(1))
|
||||||
_ = balancer1.RegisterStatusUpdater(func(up bool) {
|
_ = balancer1.RegisterStatusUpdater(func(up bool) {
|
||||||
topBalancer.SetStatus(context.WithValue(context.Background(), serviceName, "top"), "balancer1", up)
|
topBalancer.SetStatus(context.WithValue(context.Background(), serviceName, "top"), "balancer1", up)
|
||||||
// TODO(mpl): if test gets flaky, add channel or something here to signal that
|
// TODO(mpl): if test gets flaky, add channel or something here to signal that
|
||||||
// propagation is done, and wait on it before sending request.
|
// propagation is done, and wait on it before sending request.
|
||||||
})
|
})
|
||||||
topBalancer.Add("balancer2", balancer2, Int(1))
|
topBalancer.Add("balancer2", balancer2, pointer(1))
|
||||||
_ = balancer2.RegisterStatusUpdater(func(up bool) {
|
_ = balancer2.RegisterStatusUpdater(func(up bool) {
|
||||||
topBalancer.SetStatus(context.WithValue(context.Background(), serviceName, "top"), "balancer2", up)
|
topBalancer.SetStatus(context.WithValue(context.Background(), serviceName, "top"), "balancer2", up)
|
||||||
})
|
})
|
||||||
|
@ -209,8 +211,8 @@ func TestBalancerPropagate(t *testing.T) {
|
||||||
func TestBalancerAllServersZeroWeight(t *testing.T) {
|
func TestBalancerAllServersZeroWeight(t *testing.T) {
|
||||||
balancer := New(nil, false)
|
balancer := New(nil, false)
|
||||||
|
|
||||||
balancer.Add("test", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {}), Int(0))
|
balancer.Add("test", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {}), pointer(0))
|
||||||
balancer.Add("test2", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {}), Int(0))
|
balancer.Add("test2", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {}), pointer(0))
|
||||||
|
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
balancer.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/", nil))
|
balancer.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/", nil))
|
||||||
|
@ -233,12 +235,12 @@ func TestSticky(t *testing.T) {
|
||||||
balancer.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("server", "first")
|
rw.Header().Set("server", "first")
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}), Int(1))
|
}), pointer(1))
|
||||||
|
|
||||||
balancer.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("server", "second")
|
rw.Header().Set("server", "second")
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}), Int(2))
|
}), pointer(2))
|
||||||
|
|
||||||
recorder := &responseRecorder{
|
recorder := &responseRecorder{
|
||||||
ResponseRecorder: httptest.NewRecorder(),
|
ResponseRecorder: httptest.NewRecorder(),
|
||||||
|
@ -275,12 +277,12 @@ func TestSticky_FallBack(t *testing.T) {
|
||||||
balancer.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("server", "first")
|
rw.Header().Set("server", "first")
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}), Int(1))
|
}), pointer(1))
|
||||||
|
|
||||||
balancer.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("server", "second")
|
rw.Header().Set("server", "second")
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}), Int(2))
|
}), pointer(2))
|
||||||
|
|
||||||
recorder := &responseRecorder{ResponseRecorder: httptest.NewRecorder(), save: map[string]int{}}
|
recorder := &responseRecorder{ResponseRecorder: httptest.NewRecorder(), save: map[string]int{}}
|
||||||
|
|
||||||
|
@ -304,12 +306,12 @@ func TestBalancerBias(t *testing.T) {
|
||||||
balancer.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer.Add("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("server", "A")
|
rw.Header().Set("server", "A")
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}), Int(11))
|
}), pointer(11))
|
||||||
|
|
||||||
balancer.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
balancer.Add("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("server", "B")
|
rw.Header().Set("server", "B")
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}), Int(3))
|
}), pointer(3))
|
||||||
|
|
||||||
recorder := &responseRecorder{ResponseRecorder: httptest.NewRecorder(), save: map[string]int{}}
|
recorder := &responseRecorder{ResponseRecorder: httptest.NewRecorder(), save: map[string]int{}}
|
||||||
|
|
||||||
|
@ -322,8 +324,6 @@ func TestBalancerBias(t *testing.T) {
|
||||||
assert.Equal(t, wantSequence, recorder.sequence)
|
assert.Equal(t, wantSequence, recorder.sequence)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Int(v int) *int { return &v }
|
|
||||||
|
|
||||||
type responseRecorder struct {
|
type responseRecorder struct {
|
||||||
*httptest.ResponseRecorder
|
*httptest.ResponseRecorder
|
||||||
save map[string]int
|
save map[string]int
|
||||||
|
|
|
@ -74,13 +74,12 @@ func NewManagerFactory(staticConfiguration static.Configuration, routinesPool *s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build creates a service manager.
|
// Build creates a service manager.
|
||||||
func (f *ManagerFactory) Build(configuration *runtime.Configuration) *InternalHandlers {
|
func (f *ManagerFactory) Build(configuration *runtime.Configuration) *Manager {
|
||||||
svcManager := NewManager(configuration.Services, f.observabilityMgr, f.routinesPool, f.transportManager, f.proxyBuilder)
|
|
||||||
|
|
||||||
var apiHandler http.Handler
|
var apiHandler http.Handler
|
||||||
if f.api != nil {
|
if f.api != nil {
|
||||||
apiHandler = f.api(configuration)
|
apiHandler = f.api(configuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewInternalHandlers(svcManager, apiHandler, f.restHandler, f.metricsHandler, f.pingHandler, f.dashboardHandler, f.acmeHTTPHandler)
|
internalHandlers := NewInternalHandlers(apiHandler, f.restHandler, f.metricsHandler, f.pingHandler, f.dashboardHandler, f.acmeHTTPHandler)
|
||||||
|
return NewManager(configuration.Services, f.observabilityMgr, f.routinesPool, f.transportManager, f.proxyBuilder, internalHandlers)
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,12 +46,18 @@ type ProxyBuilder interface {
|
||||||
Update(configs map[string]*dynamic.ServersTransport)
|
Update(configs map[string]*dynamic.ServersTransport)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServiceBuilder is a Service builder.
|
||||||
|
type ServiceBuilder interface {
|
||||||
|
BuildHTTP(rootCtx context.Context, serviceName string) (http.Handler, error)
|
||||||
|
}
|
||||||
|
|
||||||
// Manager The service manager.
|
// Manager The service manager.
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
routinePool *safe.Pool
|
routinePool *safe.Pool
|
||||||
observabilityMgr *middleware.ObservabilityMgr
|
observabilityMgr *middleware.ObservabilityMgr
|
||||||
transportManager httputil.TransportManager
|
transportManager httputil.TransportManager
|
||||||
proxyBuilder ProxyBuilder
|
proxyBuilder ProxyBuilder
|
||||||
|
serviceBuilders []ServiceBuilder
|
||||||
|
|
||||||
services map[string]http.Handler
|
services map[string]http.Handler
|
||||||
configs map[string]*runtime.ServiceInfo
|
configs map[string]*runtime.ServiceInfo
|
||||||
|
@ -60,12 +66,13 @@ type Manager struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewManager creates a new Manager.
|
// NewManager creates a new Manager.
|
||||||
func NewManager(configs map[string]*runtime.ServiceInfo, observabilityMgr *middleware.ObservabilityMgr, routinePool *safe.Pool, transportManager httputil.TransportManager, proxyBuilder ProxyBuilder) *Manager {
|
func NewManager(configs map[string]*runtime.ServiceInfo, observabilityMgr *middleware.ObservabilityMgr, routinePool *safe.Pool, transportManager httputil.TransportManager, proxyBuilder ProxyBuilder, serviceBuilders ...ServiceBuilder) *Manager {
|
||||||
return &Manager{
|
return &Manager{
|
||||||
routinePool: routinePool,
|
routinePool: routinePool,
|
||||||
observabilityMgr: observabilityMgr,
|
observabilityMgr: observabilityMgr,
|
||||||
transportManager: transportManager,
|
transportManager: transportManager,
|
||||||
proxyBuilder: proxyBuilder,
|
proxyBuilder: proxyBuilder,
|
||||||
|
serviceBuilders: serviceBuilders,
|
||||||
services: make(map[string]http.Handler),
|
services: make(map[string]http.Handler),
|
||||||
configs: configs,
|
configs: configs,
|
||||||
healthCheckers: make(map[string]*healthcheck.ServiceHealthChecker),
|
healthCheckers: make(map[string]*healthcheck.ServiceHealthChecker),
|
||||||
|
@ -85,6 +92,18 @@ func (m *Manager) BuildHTTP(rootCtx context.Context, serviceName string) (http.H
|
||||||
return handler, nil
|
return handler, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Must be before we get configs to handle services without config.
|
||||||
|
for _, builder := range m.serviceBuilders {
|
||||||
|
handler, err := builder.BuildHTTP(rootCtx, serviceName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if handler != nil {
|
||||||
|
m.services[serviceName] = handler
|
||||||
|
return handler, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
conf, ok := m.configs[serviceName]
|
conf, ok := m.configs[serviceName]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("the service %q does not exist", serviceName)
|
return nil, fmt.Errorf("the service %q does not exist", serviceName)
|
||||||
|
|
|
@ -20,6 +20,8 @@ import (
|
||||||
"github.com/traefik/traefik/v3/pkg/testhelpers"
|
"github.com/traefik/traefik/v3/pkg/testhelpers"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func pointer[T any](v T) *T { return &v }
|
||||||
|
|
||||||
func TestGetLoadBalancer(t *testing.T) {
|
func TestGetLoadBalancer(t *testing.T) {
|
||||||
sm := Manager{
|
sm := Manager{
|
||||||
transportManager: &transportManagerMock{},
|
transportManager: &transportManagerMock{},
|
||||||
|
@ -235,7 +237,7 @@ func TestGetLoadBalancerServiceHandler(t *testing.T) {
|
||||||
serviceName: "test",
|
serviceName: "test",
|
||||||
service: &dynamic.ServersLoadBalancer{
|
service: &dynamic.ServersLoadBalancer{
|
||||||
Sticky: &dynamic.Sticky{Cookie: &dynamic.Cookie{}},
|
Sticky: &dynamic.Sticky{Cookie: &dynamic.Cookie{}},
|
||||||
PassHostHeader: func(v bool) *bool { return &v }(true),
|
PassHostHeader: pointer(true),
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
URL: serverPassHost.URL,
|
URL: serverPassHost.URL,
|
||||||
|
@ -253,7 +255,7 @@ func TestGetLoadBalancerServiceHandler(t *testing.T) {
|
||||||
desc: "PassHost doesn't pass the host instead of the IP",
|
desc: "PassHost doesn't pass the host instead of the IP",
|
||||||
serviceName: "test",
|
serviceName: "test",
|
||||||
service: &dynamic.ServersLoadBalancer{
|
service: &dynamic.ServersLoadBalancer{
|
||||||
PassHostHeader: boolPtr(false),
|
PassHostHeader: pointer(false),
|
||||||
Sticky: &dynamic.Sticky{Cookie: &dynamic.Cookie{}},
|
Sticky: &dynamic.Sticky{Cookie: &dynamic.Cookie{}},
|
||||||
Servers: []dynamic.Server{
|
Servers: []dynamic.Server{
|
||||||
{
|
{
|
||||||
|
@ -448,6 +450,48 @@ func Test1xxResponses(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type serviceBuilderFunc func(ctx context.Context, serviceName string) (http.Handler, error)
|
||||||
|
|
||||||
|
func (s serviceBuilderFunc) BuildHTTP(ctx context.Context, serviceName string) (http.Handler, error) {
|
||||||
|
return s(ctx, serviceName)
|
||||||
|
}
|
||||||
|
|
||||||
|
type internalHandler struct{}
|
||||||
|
|
||||||
|
func (internalHandler) ServeHTTP(_ http.ResponseWriter, _ *http.Request) {}
|
||||||
|
|
||||||
|
func TestManager_ServiceBuilders(t *testing.T) {
|
||||||
|
var internalHandler internalHandler
|
||||||
|
|
||||||
|
manager := NewManager(map[string]*runtime.ServiceInfo{
|
||||||
|
"test@test": {
|
||||||
|
Service: &dynamic.Service{
|
||||||
|
LoadBalancer: &dynamic.ServersLoadBalancer{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil, nil, &TransportManager{
|
||||||
|
roundTrippers: map[string]http.RoundTripper{
|
||||||
|
"default@internal": http.DefaultTransport,
|
||||||
|
},
|
||||||
|
}, nil, serviceBuilderFunc(func(rootCtx context.Context, serviceName string) (http.Handler, error) {
|
||||||
|
if strings.HasSuffix(serviceName, "@internal") {
|
||||||
|
return internalHandler, nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}))
|
||||||
|
|
||||||
|
h, err := manager.BuildHTTP(context.Background(), "test@internal")
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, internalHandler, h)
|
||||||
|
|
||||||
|
h, err = manager.BuildHTTP(context.Background(), "test@test")
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.NotNil(t, h)
|
||||||
|
|
||||||
|
_, err = manager.BuildHTTP(context.Background(), "wrong@test")
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestManager_Build(t *testing.T) {
|
func TestManager_Build(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
|
|
|
@ -27,10 +27,6 @@ import (
|
||||||
"github.com/traefik/traefik/v3/pkg/types"
|
"github.com/traefik/traefik/v3/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Int32(i int32) *int32 {
|
|
||||||
return &i
|
|
||||||
}
|
|
||||||
|
|
||||||
// LocalhostCert is a PEM-encoded TLS cert
|
// LocalhostCert is a PEM-encoded TLS cert
|
||||||
// for host example.com, www.example.com
|
// for host example.com, www.example.com
|
||||||
// expiring at Jan 29 16:00:00 2084 GMT.
|
// expiring at Jan 29 16:00:00 2084 GMT.
|
||||||
|
@ -128,7 +124,7 @@ func TestKeepConnectionWhenSameConfiguration(t *testing.T) {
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
connCount := Int32(0)
|
connCount := pointer[int32](0)
|
||||||
srv.Config.ConnState = func(conn net.Conn, state http.ConnState) {
|
srv.Config.ConnState = func(conn net.Conn, state http.ConnState) {
|
||||||
if state == http.StateNew {
|
if state == http.StateNew {
|
||||||
atomic.AddInt32(connCount, 1)
|
atomic.AddInt32(connCount, 1)
|
||||||
|
|
|
@ -79,7 +79,7 @@ func (p *Proxy) ServeTCP(conn WriteCloser) {
|
||||||
<-errChan
|
<-errChan
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Proxy) dialBackend() (WriteCloser, error) {
|
func (p *Proxy) dialBackend() (WriteCloser, error) {
|
||||||
conn, err := p.dialer.Dial("tcp", p.address)
|
conn, err := p.dialer.Dial("tcp", p.address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -88,7 +88,7 @@ func (p Proxy) dialBackend() (WriteCloser, error) {
|
||||||
return conn.(WriteCloser), nil
|
return conn.(WriteCloser), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Proxy) connCopy(dst, src WriteCloser, errCh chan error) {
|
func (p *Proxy) connCopy(dst, src WriteCloser, errCh chan error) {
|
||||||
_, err := io.Copy(dst, src)
|
_, err := io.Copy(dst, src)
|
||||||
errCh <- err
|
errCh <- err
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ func NewCertificateStore() *CertificateStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c CertificateStore) getDefaultCertificateDomains() []string {
|
func (c *CertificateStore) getDefaultCertificateDomains() []string {
|
||||||
var allCerts []string
|
var allCerts []string
|
||||||
|
|
||||||
if c.DefaultCertificate == nil {
|
if c.DefaultCertificate == nil {
|
||||||
|
@ -58,7 +58,7 @@ func (c CertificateStore) getDefaultCertificateDomains() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllDomains return a slice with all the certificate domain.
|
// GetAllDomains return a slice with all the certificate domain.
|
||||||
func (c CertificateStore) GetAllDomains() []string {
|
func (c *CertificateStore) GetAllDomains() []string {
|
||||||
allDomains := c.getDefaultCertificateDomains()
|
allDomains := c.getDefaultCertificateDomains()
|
||||||
|
|
||||||
// Get dynamic certificates
|
// Get dynamic certificates
|
||||||
|
@ -157,7 +157,7 @@ func (c *CertificateStore) GetCertificate(domains []string) *CertificateData {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetCache clears the cache in the store.
|
// ResetCache clears the cache in the store.
|
||||||
func (c CertificateStore) ResetCache() {
|
func (c *CertificateStore) ResetCache() {
|
||||||
if c.CertCache != nil {
|
if c.CertCache != nil {
|
||||||
c.CertCache.Flush()
|
c.CertCache.Flush()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,11 @@ RepositoryName = "traefik"
|
||||||
OutputType = "file"
|
OutputType = "file"
|
||||||
FileName = "traefik_changelog.md"
|
FileName = "traefik_changelog.md"
|
||||||
|
|
||||||
# example new bugfix v3.1.7
|
# example new bugfix v3.2.1
|
||||||
CurrentRef = "v3.1"
|
CurrentRef = "v3.2"
|
||||||
PreviousRef = "v3.1.6"
|
PreviousRef = "v3.2.0"
|
||||||
BaseBranch = "v3.1"
|
BaseBranch = "v3.2"
|
||||||
FutureCurrentRefName = "v3.1.7"
|
FutureCurrentRefName = "v3.2.1"
|
||||||
|
|
||||||
ThresholdPreviousRef = 10
|
ThresholdPreviousRef = 10
|
||||||
ThresholdCurrentRef = 10
|
ThresholdCurrentRef = 10
|
||||||
|
|
Loading…
Reference in a new issue