mirror of
https://github.com/containous/traefik.git
synced 2025-09-19 01:44:23 +03:00
Compare commits
47 Commits
v3.0.0-rc2
...
v3.0.0-rc5
Author | SHA1 | Date | |
---|---|---|---|
|
da7bb5fc25 | ||
|
34bd611131 | ||
|
b9b7527762 | ||
|
240b83b773 | ||
|
584839e00b | ||
|
099c7e9444 | ||
|
83a5c5cfbd | ||
|
c1d9b9ee1f | ||
|
d53f5f01a0 | ||
|
4e11bf3c38 | ||
|
1a266c661a | ||
|
bda4f50eae | ||
|
19e6170fa5 | ||
|
0017471f0d | ||
|
76723b1288 | ||
|
cef842245c | ||
|
f69fd43122 | ||
|
e5062cef42 | ||
|
998c6174cd | ||
|
ac1753a614 | ||
|
d3516aec31 | ||
|
2c6418e17a | ||
|
fdf27eb644 | ||
|
945ff9b0f9 | ||
|
bbd5846c6a | ||
|
9f145dbc28 | ||
|
c84b510f0d | ||
|
2bc3fa7b4b | ||
|
fc897f6756 | ||
|
c31f5df854 | ||
|
b636b21167 | ||
|
167bdb0d53 | ||
|
7f29595c0a | ||
|
3fcf265d80 | ||
|
618fb5f232 | ||
|
d94e676083 | ||
|
141abce2d5 | ||
|
fc875b38e0 | ||
|
39fe3869b6 | ||
|
d582e01892 | ||
|
75790e0ab8 | ||
|
1391c35978 | ||
|
7bda07a422 | ||
|
9b6af61d1b | ||
|
5edac5eccd | ||
|
83e4abdb30 | ||
|
4e1e2f5ed0 |
12
.github/workflows/codeql.yml
vendored
12
.github/workflows/codeql.yml
vendored
@@ -30,9 +30,15 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: setup go
|
||||
uses: actions/setup-go@v5
|
||||
if: ${{ matrix.language == 'go' }}
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -46,7 +52,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
@@ -59,6 +65,6 @@ jobs:
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
2
.github/workflows/validate.yaml
vendored
2
.github/workflows/validate.yaml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
|
||||
env:
|
||||
GO_VERSION: '1.22'
|
||||
GOLANGCI_LINT_VERSION: v1.56.2
|
||||
GOLANGCI_LINT_VERSION: v1.57.0
|
||||
MISSSPELL_VERSION: v0.4.1
|
||||
|
||||
jobs:
|
||||
|
@@ -1,8 +1,5 @@
|
||||
run:
|
||||
timeout: 10m
|
||||
skip-files: []
|
||||
skip-dirs:
|
||||
- pkg/provider/kubernetes/crd/generated/
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
@@ -209,11 +206,16 @@ linters:
|
||||
- maintidx # kind of duplicate of gocyclo
|
||||
- nonamedreturns # Too strict
|
||||
- gosmopolitan # not relevant
|
||||
- exportloopref # Useless with go1.22
|
||||
- musttag
|
||||
- intrange # bug (fixed in golangci-lint v1.58)
|
||||
|
||||
issues:
|
||||
exclude-use-default: false
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
exclude-dirs:
|
||||
- pkg/provider/kubernetes/crd/generated/
|
||||
exclude:
|
||||
- 'Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked'
|
||||
- "should have a package comment, unless it's in another file for this package"
|
||||
|
@@ -25,7 +25,7 @@ global_job_config:
|
||||
- export "PATH=${GOPATH}/bin:${PATH}"
|
||||
- mkdir -vp "${SEMAPHORE_GIT_DIR}" "${GOPATH}/bin"
|
||||
- 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.56.2
|
||||
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "${GOPATH}/bin" v1.57.0
|
||||
- curl -sSfL https://gist.githubusercontent.com/traefiker/6d7ac019c11d011e4f131bb2cca8900e/raw/goreleaser.sh | bash -s -- -b "${GOPATH}/bin"
|
||||
- checkout
|
||||
- cache restore traefik-$(checksum go.sum)
|
||||
|
88
CHANGELOG.md
88
CHANGELOG.md
@@ -1,3 +1,91 @@
|
||||
## [v3.0.0-rc5](https://github.com/traefik/traefik/tree/v3.0.0-rc4) (2024-04-11)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v3.0.0-rc4...v3.0.0-rc5)
|
||||
|
||||
**Misc:**
|
||||
- Merge current v2.11 into v3.0 ([#10604](https://github.com/traefik/traefik/pull/10604) by [ldez](https://github.com/ldez))
|
||||
|
||||
## [v2.11.2](https://github.com/traefik/traefik/tree/v2.11.2) (2024-04-11)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.11.1...v2.11.2)
|
||||
|
||||
**Bug fixes:**
|
||||
- **[server]** Revert LingeringTimeout and change default value for ReadTimeout ([#10599](https://github.com/traefik/traefik/pull/10599) by [kevinpollet](https://github.com/kevinpollet))
|
||||
- **[server]** Set default ReadTimeout value to 60s ([#10602](https://github.com/traefik/traefik/pull/10602) by [rtribotte](https://github.com/rtribotte))
|
||||
|
||||
## [v3.0.0-rc4](https://github.com/traefik/traefik/tree/v3.0.0-rc4) (2024-04-10)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v3.0.0-rc3...v3.0.0-rc4)
|
||||
|
||||
**Enhancements:**
|
||||
- **[k8s/gatewayapi]** Add option to set Gateway status address ([#10582](https://github.com/traefik/traefik/pull/10582) by [kevinpollet](https://github.com/kevinpollet))
|
||||
- **[k8s/gatewayapi]** Handle middlewares in filters extension reference ([#10511](https://github.com/traefik/traefik/pull/10511) by [youkoulayley](https://github.com/youkoulayley))
|
||||
- **[k8s/gatewayapi]** Toggle support for experimental channel ([#10435](https://github.com/traefik/traefik/pull/10435) by [SantoDE](https://github.com/SantoDE))
|
||||
- **[k8s/ingress,k8s/crd,k8s,k8s/gatewayapi]** Use runtime.Object in routerTransform ([#10523](https://github.com/traefik/traefik/pull/10523) by [juliens](https://github.com/juliens))
|
||||
- **[nomad]** Allow empty services ([#10375](https://github.com/traefik/traefik/pull/10375) by [chrispruitt](https://github.com/chrispruitt))
|
||||
- **[webui,middleware,k8s/gatewayapi]** Support RequestHeaderModifier filter ([#10521](https://github.com/traefik/traefik/pull/10521) by [rtribotte](https://github.com/rtribotte))
|
||||
|
||||
**Bug fixes:**
|
||||
- **[docker]** Fix struct names in comment ([#10503](https://github.com/traefik/traefik/pull/10503) by [hishope](https://github.com/hishope))
|
||||
- **[logs]** Avoid cumulative send anonymous usage log ([#10579](https://github.com/traefik/traefik/pull/10579) by [mmatur](https://github.com/mmatur))
|
||||
- **[rules]** Support regexp in path/pathprefix in matcher v2 ([#10546](https://github.com/traefik/traefik/pull/10546) by [youkoulayley](https://github.com/youkoulayley))
|
||||
- **[webui]** Add missing Docker Swarm logo ([#10529](https://github.com/traefik/traefik/pull/10529) by [ldez](https://github.com/ldez))
|
||||
|
||||
**Documentation:**
|
||||
- Fix typo and improve explanation on internal resources ([#10563](https://github.com/traefik/traefik/pull/10563) by [mloiseleur](https://github.com/mloiseleur))
|
||||
- Fix typo in dialer_test.go ([#10552](https://github.com/traefik/traefik/pull/10552) by [eltociear](https://github.com/eltociear))
|
||||
|
||||
**Misc:**
|
||||
- Merge branch v2.11 into v3.0 ([#10587](https://github.com/traefik/traefik/pull/10587) by [kevinpollet](https://github.com/kevinpollet))
|
||||
- Merge current v2.11 into v3.0 ([#10566](https://github.com/traefik/traefik/pull/10566) by [mmatur](https://github.com/mmatur))
|
||||
- Merge current v2.11 into v3.0 ([#10564](https://github.com/traefik/traefik/pull/10564) by [ldez](https://github.com/ldez))
|
||||
|
||||
## [v2.11.1](https://github.com/traefik/traefik/tree/v2.11.1) (2024-04-10)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.11.0...v2.11.1)
|
||||
|
||||
**Bug fixes:**
|
||||
- **[acme,tls]** Enforce handling of ACME-TLS/1 challenges ([#10536](https://github.com/traefik/traefik/pull/10536) by [rtribotte](https://github.com/rtribotte))
|
||||
- **[acme]** Update go-acme/lego to v4.16.1 ([#10508](https://github.com/traefik/traefik/pull/10508) by [ldez](https://github.com/ldez))
|
||||
- **[acme]** Close created file in ACME local store CheckFile func ([#10574](https://github.com/traefik/traefik/pull/10574) by [testwill](https://github.com/testwill))
|
||||
- **[docker,http3]** Update to quic-go v0.42.0 and docker/cli v24.0.9 ([#10572](https://github.com/traefik/traefik/pull/10572) by [mloiseleur](https://github.com/mloiseleur))
|
||||
- **[docker,marathon,rancher,ecs,tls,nomad]** Allow to configure TLSStore default generated certificate with labels ([#10439](https://github.com/traefik/traefik/pull/10439) by [kevinpollet](https://github.com/kevinpollet))
|
||||
- **[ecs]** Adjust ECS network interface detection logic ([#10550](https://github.com/traefik/traefik/pull/10550) by [amaxine](https://github.com/amaxine))
|
||||
- **[logs,tls]** Fix log when default TLSStore and TLSOptions are defined multiple times ([#10499](https://github.com/traefik/traefik/pull/10499) by [rtribotte](https://github.com/rtribotte))
|
||||
- **[middleware]** Allow empty replacement with ReplacePathRegex middleware ([#10538](https://github.com/traefik/traefik/pull/10538) by [rtribotte](https://github.com/rtribotte))
|
||||
- **[plugins]** Update Yaegi to v0.16.1 ([#10565](https://github.com/traefik/traefik/pull/10565) by [ldez](https://github.com/ldez))
|
||||
- **[provider,rules]** Don't allow routers higher than internal ones ([#10428](https://github.com/traefik/traefik/pull/10428) by [ldez](https://github.com/ldez))
|
||||
- **[rules]** Reserve priority range for internal routers ([#10541](https://github.com/traefik/traefik/pull/10541) by [youkoulayley](https://github.com/youkoulayley))
|
||||
- **[server,tcp]** Introduce Lingering Timeout ([#10569](https://github.com/traefik/traefik/pull/10569) by [rtribotte](https://github.com/rtribotte))
|
||||
- **[tcp]** Enforce failure for TCP HostSNI with hostname ([#10540](https://github.com/traefik/traefik/pull/10540) by [youkoulayley](https://github.com/youkoulayley))
|
||||
- **[tracing]** Bump Elastic APM to v2.4.8 ([#10512](https://github.com/traefik/traefik/pull/10512) by [rtribotte](https://github.com/rtribotte))
|
||||
- **[webui]** Fix dashboard exposition through a router ([#10518](https://github.com/traefik/traefik/pull/10518) by [mmatur](https://github.com/mmatur))
|
||||
- **[webui]** Display IPAllowlist middleware configuration in dashboard ([#10459](https://github.com/traefik/traefik/pull/10459) by [youkoulayley](https://github.com/youkoulayley))
|
||||
- **[webui]** Make text more readable in dark mode ([#10473](https://github.com/traefik/traefik/pull/10473) by [hood](https://github.com/hood))
|
||||
- **[webui]** Migrate to Quasar 2.x and Vue.js 3.x ([#10416](https://github.com/traefik/traefik/pull/10416) by [andsarr](https://github.com/andsarr))
|
||||
- **[webui]** Add a horizontal scroll for the mobile view ([#10480](https://github.com/traefik/traefik/pull/10480) by [framebassman](https://github.com/framebassman))
|
||||
|
||||
**Documentation:**
|
||||
- **[acme]** Update gandiv5 env variable in providers table ([#10506](https://github.com/traefik/traefik/pull/10506) by [dominiwe](https://github.com/dominiwe))
|
||||
- **[acme]** Fix multiple dns provider documentation ([#10496](https://github.com/traefik/traefik/pull/10496) by [mmatur](https://github.com/mmatur))
|
||||
- **[docker]** Fix paragraph in entrypoints and Docker docs ([#10491](https://github.com/traefik/traefik/pull/10491) by [luigir-it](https://github.com/luigir-it))
|
||||
- **[k8s]** Improve middleware example ([#10532](https://github.com/traefik/traefik/pull/10532) by [mloiseleur](https://github.com/mloiseleur))
|
||||
- **[metrics]** Fix host header mention in prometheus metrics doc ([#10502](https://github.com/traefik/traefik/pull/10502) by [MorphBonehunter](https://github.com/MorphBonehunter))
|
||||
- **[metrics]** Fix typo in statsd metrics docs ([#10437](https://github.com/traefik/traefik/pull/10437) by [xpac1985](https://github.com/xpac1985))
|
||||
- **[middleware]** Improve excludedIPs example with IPWhiteList and IPAllowList middleware ([#10554](https://github.com/traefik/traefik/pull/10554) by [mloiseleur](https://github.com/mloiseleur))
|
||||
- **[nomad]** Improve documentation about Nomad ACL minimum rights ([#10482](https://github.com/traefik/traefik/pull/10482) by [Thadir](https://github.com/Thadir))
|
||||
- **[server]** Add specification for TCP TLS routers in documentation ([#10510](https://github.com/traefik/traefik/pull/10510) by [shivanipawar00](https://github.com/shivanipawar00))
|
||||
- **[tls]** Fix default value for peerCertURI option ([#10470](https://github.com/traefik/traefik/pull/10470) by [marcmognol](https://github.com/marcmognol))
|
||||
- Update releases page ([#10449](https://github.com/traefik/traefik/pull/10449) by [ldez](https://github.com/ldez))
|
||||
- Update releases page ([#10443](https://github.com/traefik/traefik/pull/10443) by [ldez](https://github.com/ldez))
|
||||
- Add youkoulayley to maintainers ([#10517](https://github.com/traefik/traefik/pull/10517) by [emilevauge](https://github.com/emilevauge))
|
||||
- Add sdelicata to maintainers ([#10515](https://github.com/traefik/traefik/pull/10515) by [emilevauge](https://github.com/emilevauge))
|
||||
|
||||
**Misc:**
|
||||
- **[webui]** Modify the Hub Button ([#10583](https://github.com/traefik/traefik/pull/10583) by [mdeliatf](https://github.com/mdeliatf))
|
||||
|
||||
## [v3.0.0-rc3](https://github.com/traefik/traefik/tree/v3.0.0-rc3) (2024-03-13)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v3.0.0-rc2...v3.0.0-rc3)
|
||||
|
||||
**Misc:**
|
||||
- Merge branch v2.11 into v3.0 ([#10519](https://github.com/traefik/traefik/pull/10519) by [rtribotte](https://github.com/rtribotte))
|
||||
|
||||
## [v3.0.0-rc2](https://github.com/traefik/traefik/tree/v3.0.0-rc2) (2024-03-12)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v3.0.0-rc1...v3.0.0-rc2)
|
||||
|
||||
|
@@ -593,16 +593,16 @@ func checkNewVersion() {
|
||||
}
|
||||
|
||||
func stats(staticConfiguration *static.Configuration) {
|
||||
logger := log.Info()
|
||||
logger := log.With().Logger()
|
||||
|
||||
if staticConfiguration.Global.SendAnonymousUsage {
|
||||
logger.Msg(`Stats collection is enabled.`)
|
||||
logger.Msg(`Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration.`)
|
||||
logger.Msg(`Help us improve Traefik by leaving this feature on :)`)
|
||||
logger.Msg(`More details on: https://doc.traefik.io/traefik/contributing/data-collection/`)
|
||||
logger.Info().Msg(`Stats collection is enabled.`)
|
||||
logger.Info().Msg(`Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration.`)
|
||||
logger.Info().Msg(`Help us improve Traefik by leaving this feature on :)`)
|
||||
logger.Info().Msg(`More details on: https://doc.traefik.io/traefik/contributing/data-collection/`)
|
||||
collect(staticConfiguration)
|
||||
} else {
|
||||
logger.Msg(`
|
||||
logger.Info().Msg(`
|
||||
Stats collection is disabled.
|
||||
Help us improve Traefik by turning this feature on :)
|
||||
More details on: https://doc.traefik.io/traefik/contributing/data-collection/
|
||||
|
@@ -95,7 +95,6 @@ func TestAppendCertMetric(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -21,6 +21,8 @@ description: "Traefik Proxy is an open source software with a thriving community
|
||||
* Harold Ozouf [@jspdown](https://github.com/jspdown)
|
||||
* Tom Moulard [@tommoulard](https://github.com/tommoulard)
|
||||
* Landry Benguigui [@lbenguigui](https://github.com/lbenguigui)
|
||||
* Simon Delicata [@sdelicata](https://github.com/sdelicata)
|
||||
* Baptiste Mayelle [@youkoulayley](https://github.com/youkoulayley)
|
||||
|
||||
## Past Maintainers
|
||||
|
||||
|
@@ -8,11 +8,11 @@ description: "Learn how to use IPAllowList in HTTP middleware for limiting clien
|
||||
Limiting Clients to Specific IPs
|
||||
{: .subtitle }
|
||||
|
||||
IPAllowList accepts / refuses requests based on the client IP.
|
||||
IPAllowList limits allowed requests based on the client IP.
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
```yaml tab="Docker & Swarm"
|
||||
```yaml tab="Docker"
|
||||
# Accepts request from defined IP
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7"
|
||||
@@ -35,6 +35,18 @@ spec:
|
||||
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7"
|
||||
```
|
||||
|
||||
```json tab="Marathon"
|
||||
"labels": {
|
||||
"traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange": "127.0.0.1/32,192.168.1.7"
|
||||
}
|
||||
```
|
||||
|
||||
```yaml tab="Rancher"
|
||||
# Accepts request from defined IP
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
# Accepts request from defined IP
|
||||
http:
|
||||
@@ -57,6 +69,8 @@ http:
|
||||
|
||||
### `sourceRange`
|
||||
|
||||
_Required_
|
||||
|
||||
The `sourceRange` option sets the allowed IPs (or ranges of allowed IPs by using CIDR notation).
|
||||
|
||||
### `ipStrategy`
|
||||
@@ -83,7 +97,7 @@ The `depth` option tells Traefik to use the `X-Forwarded-For` header and take th
|
||||
| `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `3` | `"11.0.0.1"` |
|
||||
| `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `5` | `""` |
|
||||
|
||||
```yaml tab="Docker & Swarm"
|
||||
```yaml tab="Docker"
|
||||
# Allowlisting Based on `X-Forwarded-For` with `depth=2`
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7"
|
||||
@@ -111,6 +125,20 @@ spec:
|
||||
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth=2"
|
||||
```
|
||||
|
||||
```json tab="Marathon"
|
||||
"labels": {
|
||||
"traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange": "127.0.0.1/32, 192.168.1.7",
|
||||
"traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth": "2"
|
||||
}
|
||||
```
|
||||
|
||||
```yaml tab="Rancher"
|
||||
# Whitelisting Based on `X-Forwarded-For` with `depth=2`
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7"
|
||||
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth=2"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
# Allowlisting Based on `X-Forwarded-For` with `depth=2`
|
||||
http:
|
||||
@@ -149,9 +177,10 @@ http:
|
||||
| `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `"15.0.0.1,16.0.0.1"` | `"13.0.0.1"` |
|
||||
| `"10.0.0.1,11.0.0.1"` | `"10.0.0.1,11.0.0.1"` | `""` |
|
||||
|
||||
```yaml tab="Docker & Swarm"
|
||||
```yaml tab="Docker"
|
||||
# Exclude from `X-Forwarded-For`
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourceRange=127.0.0.1/32, 192.168.1.0/24"
|
||||
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7"
|
||||
```
|
||||
|
||||
@@ -163,6 +192,9 @@ metadata:
|
||||
name: test-ipallowlist
|
||||
spec:
|
||||
ipAllowList:
|
||||
sourceRange:
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.0/24
|
||||
ipStrategy:
|
||||
excludedIPs:
|
||||
- 127.0.0.1/32
|
||||
@@ -171,25 +203,44 @@ spec:
|
||||
|
||||
```yaml tab="Consul Catalog"
|
||||
# Exclude from `X-Forwarded-For`
|
||||
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourceRange=127.0.0.1/32, 192.168.1.0/24"
|
||||
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7"
|
||||
```
|
||||
|
||||
```json tab="Marathon"
|
||||
"labels": {
|
||||
"traefik.http.middlewares.test-ipallowlist.ipallowlist.sourceRange=127.0.0.1/32, 192.168.1.0/24"
|
||||
"traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips": "127.0.0.1/32, 192.168.1.7"
|
||||
}
|
||||
```
|
||||
|
||||
```yaml tab="Rancher"
|
||||
# Exclude from `X-Forwarded-For`
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourceRange=127.0.0.1/32, 192.168.1.0/24"
|
||||
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
# Exclude from `X-Forwarded-For`
|
||||
http:
|
||||
middlewares:
|
||||
test-ipallowlist:
|
||||
ipAllowList:
|
||||
sourceRange:
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.0/24
|
||||
ipStrategy:
|
||||
excludedIPs:
|
||||
- "127.0.0.1/32"
|
||||
- "192.168.1.7"
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.7
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
# Exclude from `X-Forwarded-For`
|
||||
[http.middlewares]
|
||||
[http.middlewares.test-ipallowlist.ipAllowList]
|
||||
sourceRange = ["127.0.0.1/32", "192.168.1.0/24"]
|
||||
[http.middlewares.test-ipallowlist.ipAllowList.ipStrategy]
|
||||
excludedIPs = ["127.0.0.1/32", "192.168.1.7"]
|
||||
```
|
||||
|
@@ -10,7 +10,7 @@ Limiting Clients to Specific IPs
|
||||
|
||||

|
||||
|
||||
IPWhiteList accepts / refuses requests based on the client IP.
|
||||
IPWhiteList limits allowed requests based on the client IP.
|
||||
|
||||
!!! warning
|
||||
|
||||
@@ -63,6 +63,8 @@ http:
|
||||
|
||||
### `sourceRange`
|
||||
|
||||
_Required_
|
||||
|
||||
The `sourceRange` option sets the allowed IPs (or ranges of allowed IPs by using CIDR notation).
|
||||
|
||||
### `ipStrategy`
|
||||
@@ -158,6 +160,7 @@ http:
|
||||
```yaml tab="Docker"
|
||||
# Exclude from `X-Forwarded-For`
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourceRange=127.0.0.1/32, 192.168.1.0/24"
|
||||
- "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7"
|
||||
```
|
||||
|
||||
@@ -170,6 +173,9 @@ metadata:
|
||||
spec:
|
||||
ipWhiteList:
|
||||
ipStrategy:
|
||||
sourceRange:
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.0/24
|
||||
excludedIPs:
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.7
|
||||
@@ -177,6 +183,7 @@ spec:
|
||||
|
||||
```yaml tab="Consul Catalog"
|
||||
# Exclude from `X-Forwarded-For`
|
||||
- "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.sourceRange=127.0.0.1/32, 192.168.1.0/24"
|
||||
- "traefik.http.middlewares.test-ipwhitelist.ipwhitelist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7"
|
||||
```
|
||||
|
||||
@@ -186,16 +193,20 @@ http:
|
||||
middlewares:
|
||||
test-ipwhitelist:
|
||||
ipWhiteList:
|
||||
sourceRange:
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.0/24
|
||||
ipStrategy:
|
||||
excludedIPs:
|
||||
- "127.0.0.1/32"
|
||||
- "192.168.1.7"
|
||||
- 127.0.0.1/32
|
||||
- 192.168.1.7
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
# Exclude from `X-Forwarded-For`
|
||||
[http.middlewares]
|
||||
[http.middlewares.test-ipwhitelist.ipWhiteList]
|
||||
sourceRange = ["127.0.0.1/32", "192.168.1.0/24"]
|
||||
[http.middlewares.test-ipwhitelist.ipWhiteList.ipStrategy]
|
||||
excludedIPs = ["127.0.0.1/32", "192.168.1.7"]
|
||||
```
|
||||
|
@@ -8,7 +8,7 @@ description: "Learn how to use IPAllowList in TCP middleware for limiting client
|
||||
Limiting Clients to Specific IPs
|
||||
{: .subtitle }
|
||||
|
||||
IPAllowList accepts / refuses connections based on the client IP.
|
||||
IPAllowList limits allowed requests based on the client IP.
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
|
@@ -92,6 +92,34 @@ Docker provider `tls.CAOptional` option has been removed in v3, as TLS client au
|
||||
|
||||
The `tls.caOptional` option should be removed from the Docker provider static configuration.
|
||||
|
||||
### Kubernetes Gateway API
|
||||
|
||||
#### Experimental Channel Resources (TLSRoute and TCPRoute)
|
||||
|
||||
In v3, the Kubernetes Gateway API provider does not enable support for the experimental channel API resources by default.
|
||||
|
||||
##### Remediation
|
||||
|
||||
The `experimentalChannel` option should be used to enable the support for the experimental channel API resources.
|
||||
|
||||
??? example "An example usage of the Kubernetes Gateway API provider with experimental channel support enabled"
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
kubernetesGateway:
|
||||
experimentalChannel: true
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[providers.kubernetesGateway]
|
||||
experimentalChannel = true
|
||||
# ...
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--providers.kubernetesgateway.experimentalchannel=true
|
||||
```
|
||||
|
||||
### Experimental Configuration
|
||||
|
||||
#### HTTP3
|
||||
@@ -696,7 +724,7 @@ Here are two possible transition strategies:
|
||||
|
||||
Please check the [OpenTelemetry Tracing provider documention](../observability/tracing/opentelemetry.md) for more information.
|
||||
|
||||
#### Internal Resources Observability (AccessLogs, Metrics and Tracing)
|
||||
#### Internal Resources Observability
|
||||
|
||||
In v3, observability for internal routers or services (e.g.: `ping@internal`) is disabled by default.
|
||||
To enable it one should use the new `addInternals` option for AccessLogs, Metrics or Tracing.
|
||||
@@ -704,4 +732,4 @@ Please take a look at the observability documentation for more information:
|
||||
|
||||
- [AccessLogs](../observability/access-logs.md#addinternals)
|
||||
- [Metrics](../observability/metrics/overview.md#addinternals)
|
||||
- [AccessLogs](../observability/tracing/overview.md#addinternals)
|
||||
- [Tracing](../observability/tracing/overview.md#addinternals)
|
||||
|
@@ -563,3 +563,80 @@ To enable these ciphers, please set the option `CipherSuites` in your [TLS confi
|
||||
> (https://go.dev/doc/go1.22#crypto/tls)
|
||||
|
||||
To enable TLS 1.0, please set the option `MinVersion` to `VersionTLS10` in your [TLS configuration](https://doc.traefik.io/traefik/https/tls/#cipher-suites) or set the environment variable `GODEBUG=tls10server=1`.
|
||||
|
||||
## v2.11.1
|
||||
|
||||
### Maximum Router Priority Value
|
||||
|
||||
Before v2.11.1, the maximum user-defined router priority value is:
|
||||
|
||||
- `MaxInt32` for 32-bit platforms,
|
||||
- `MaxInt64` for 64-bit platforms.
|
||||
|
||||
Please check out the [go documentation](https://pkg.go.dev/math#pkg-constants) for more information.
|
||||
|
||||
In v2.11.1, Traefik reserves a range of priorities for its internal routers and now,
|
||||
the maximum user-defined router priority value is:
|
||||
|
||||
- `(MaxInt32 - 1000)` for 32-bit platforms,
|
||||
- `(MaxInt64 - 1000)` for 64-bit platforms.
|
||||
|
||||
### EntryPoint.Transport.RespondingTimeouts.<Timeout>
|
||||
|
||||
Starting with `v2.11.1` the following timeout options are deprecated:
|
||||
|
||||
- `<entryPoint>.transport.respondingTimeouts.readTimeout`
|
||||
- `<entryPoint>.transport.respondingTimeouts.writeTimeout`
|
||||
- `<entryPoint>.transport.respondingTimeouts.idleTimeout`
|
||||
|
||||
They have been replaced by:
|
||||
|
||||
- `<entryPoint>.transport.respondingTimeouts.http.readTimeout`
|
||||
- `<entryPoint>.transport.respondingTimeouts.http.writeTimeout`
|
||||
- `<entryPoint>.transport.respondingTimeouts.http.idleTimeout`
|
||||
|
||||
### EntryPoint.Transport.RespondingTimeouts.TCP.LingeringTimeout
|
||||
|
||||
Starting with `v2.11.1` a new `lingeringTimeout` entryPoints option has been introduced, with a default value of 2s.
|
||||
|
||||
The lingering timeout defines the maximum duration between each TCP read operation on the connection.
|
||||
As a layer 4 timeout, it applies during HTTP handling but respects the configured HTTP server `readTimeout`.
|
||||
|
||||
This change avoids Traefik instances with the default configuration hanging while waiting for bytes to be read on the connection.
|
||||
|
||||
We suggest to adapt this value accordingly to your situation.
|
||||
The new default value is purposely narrowed and can close the connection too early.
|
||||
|
||||
Increasing the `lingeringTimeout` value could be the solution notably if you are dealing with the following errors:
|
||||
|
||||
- TCP: `Error while handling TCP connection: readfrom tcp X.X.X.X:X->X.X.X.X:X: read tcp X.X.X.X:X->X.X.X.X:X: i/o timeout`
|
||||
- HTTP: `'499 Client Closed Request' caused by: context canceled`
|
||||
- HTTP: `ReverseProxy read error during body copy: read tcp X.X.X.X:X->X.X.X.X:X: use of closed network connection`
|
||||
|
||||
## v2.11.2
|
||||
|
||||
### LingeringTimeout
|
||||
|
||||
Starting with `v2.11.2` the `<entrypoint>.transport.respondingTimeouts.tcp.lingeringTimeout` introduced in `v2.11.1` has been removed.
|
||||
|
||||
### RespondingTimeouts.TCP and RespondingTimeouts.HTTP
|
||||
|
||||
Starting with `v2.11.2` the `respondingTimeouts.tcp` and `respondingTimeouts.http` sections introduced in `v2.11.1` have been removed.
|
||||
To configure responding timeouts
|
||||
|
||||
### EntryPoint.Transport.RespondingTimeouts.ReadTimeout
|
||||
|
||||
Starting with `v2.11.2` the entryPoints [`readTimeout`](../routing/entrypoints.md#respondingtimeouts) option default value changed to 60 seconds.
|
||||
|
||||
For HTTP, this option defines the maximum duration for reading the entire request, including the body.
|
||||
For TCP, this option defines the maximum duration for the first bytes to be read on the connection.
|
||||
|
||||
The default value was previously set to zero, which means no timeout.
|
||||
|
||||
This change has been done to avoid Traefik instances with the default configuration to be hanging forever while waiting for bytes to be read on the connection.
|
||||
|
||||
Increasing the `readTimeout` value could be the solution notably if you are dealing with the following errors:
|
||||
|
||||
- TCP: `Error while handling TCP connection: readfrom tcp X.X.X.X:X->X.X.X.X:X: read tcp X.X.X.X:X->X.X.X.X:X: i/o timeout`
|
||||
- HTTP: `'499 Client Closed Request' caused by: context canceled`
|
||||
- HTTP: `ReverseProxy read error during body copy: read tcp X.X.X.X:X->X.X.X.X:X: use of closed network connection`
|
||||
|
@@ -30,7 +30,7 @@ accessLog: {}
|
||||
|
||||
_Optional, Default="false"_
|
||||
|
||||
Enables accessLogs for internal resources.
|
||||
Enables accessLogs for internal resources (e.g.: `ping@internal`).
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
accesslog:
|
||||
@@ -187,7 +187,7 @@ accessLog:
|
||||
|
||||
[accessLog.fields]
|
||||
defaultMode = "keep"
|
||||
|
||||
|
||||
[accessLog.fields.names]
|
||||
"ClientUsername" = "drop"
|
||||
|
||||
|
@@ -21,7 +21,7 @@ and [Kubernetes](https://grafana.com/grafana/dashboards/17347) deployments.
|
||||
|
||||
_Optional, Default="false"_
|
||||
|
||||
Enables metrics for internal resources.
|
||||
Enables metrics for internal resources (e.g.: `ping@internals`).
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
metrics:
|
||||
|
@@ -36,7 +36,7 @@ tracing: {}
|
||||
|
||||
_Optional, Default="false"_
|
||||
|
||||
Enables tracing for internal resources.
|
||||
Enables tracing for internal resources (e.g.: `ping@internal`).
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
tracing:
|
||||
@@ -159,4 +159,4 @@ tracing:
|
||||
|
||||
```bash tab="CLI"
|
||||
--tracing.capturedResponseHeaders[0]=X-CustomHeader
|
||||
```
|
||||
```
|
||||
|
@@ -212,6 +212,108 @@ providers:
|
||||
--providers.kubernetesgateway.namespaces=default,production
|
||||
```
|
||||
|
||||
### `statusAddress`
|
||||
|
||||
#### `ip`
|
||||
|
||||
_Optional, Default: ""_
|
||||
|
||||
This IP will get copied to the Gateway `status.addresses`, and currently only supports one IP value (IPv4 or IPv6).
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
kubernetesGateway:
|
||||
statusAddress:
|
||||
ip: "1.2.3.4"
|
||||
# ...
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[providers.kubernetesGateway.statusAddress]
|
||||
ip = "1.2.3.4"
|
||||
# ...
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--providers.kubernetesgateway.statusaddress.ip=1.2.3.4
|
||||
```
|
||||
|
||||
#### `hostname`
|
||||
|
||||
_Optional, Default: ""_
|
||||
|
||||
This Hostname will get copied to the Gateway `status.addresses`.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
kubernetesGateway:
|
||||
statusAddress:
|
||||
hostname: "example.net"
|
||||
# ...
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[providers.kubernetesGateway.statusAddress]
|
||||
hostname = "example.net"
|
||||
# ...
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--providers.kubernetesgateway.statusaddress.hostname=example.net
|
||||
```
|
||||
|
||||
#### `service`
|
||||
|
||||
_Optional_
|
||||
|
||||
The Kubernetes service to copy status addresses from.
|
||||
When using third parties tools like External-DNS, this option can be used to copy the service `loadbalancer.status` (containing the service's endpoints IPs) to the gateways.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
kubernetesGateway:
|
||||
statusAddress:
|
||||
service:
|
||||
namespace: default
|
||||
name: foo
|
||||
# ...
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[providers.kubernetesGateway.statusAddress.service]
|
||||
namespace = "default"
|
||||
name = "foo"
|
||||
# ...
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--providers.kubernetesgateway.statusaddress.service.namespace=default
|
||||
--providers.kubernetesgateway.statusaddress.service.name=foo
|
||||
```
|
||||
|
||||
### `experimentalChannel`
|
||||
|
||||
_Optional, Default: false_
|
||||
|
||||
Toggles support for the Experimental Channel resources ([Gateway API release channels documentation](https://gateway-api.sigs.k8s.io/concepts/versioning/#release-channels)).
|
||||
This option currently enables support for `TCPRoute` and `TLSRoute`.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
kubernetesGateway:
|
||||
experimentalChannel: true
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[providers.kubernetesGateway]
|
||||
experimentalChannel = true
|
||||
# ...
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--providers.kubernetesgateway.experimentalchannel=true
|
||||
```
|
||||
|
||||
### `labelselector`
|
||||
|
||||
_Optional, Default: ""_
|
||||
|
@@ -163,6 +163,7 @@ providers:
|
||||
_Optional, Default=""_
|
||||
|
||||
Token is used to provide a per-request ACL token, if Nomad ACLs are enabled.
|
||||
The appropriate ACL privilege for this token is 'read-job', as outlined in the [Nomad documentation on ACL](https://developer.hashicorp.com/nomad/tutorials/access-control/access-control-policies).
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
@@ -511,3 +512,27 @@ providers:
|
||||
--providers.nomad.namespaces=ns1,ns2
|
||||
# ...
|
||||
```
|
||||
|
||||
### `allowEmptyServices`
|
||||
|
||||
_Optional, Default: false_
|
||||
|
||||
If the parameter is set to `true`,
|
||||
it allows the creation of an empty [servers load balancer](../routing/services/index.md#servers-load-balancer) if the targeted Nomad service has no endpoints available. This results in a `503` HTTP response instead of a `404`.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
nomad:
|
||||
allowEmptyServices: true
|
||||
# ...
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[providers.nomad]
|
||||
allowEmptyServices = true
|
||||
# ...
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--providers.nomad.allowEmptyServices=true
|
||||
```
|
||||
|
@@ -1303,7 +1303,7 @@ spec:
|
||||
ipAllowList:
|
||||
description: |-
|
||||
IPAllowList holds the IP allowlist middleware configuration.
|
||||
This middleware accepts / refuses requests based on the client IP.
|
||||
This middleware limits allowed requests based on the client IP.
|
||||
More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/ipallowlist/
|
||||
properties:
|
||||
ipStrategy:
|
||||
@@ -1357,7 +1357,7 @@ spec:
|
||||
type: object
|
||||
sourceRange:
|
||||
description: SourceRange defines the set of allowed IPs (or ranges
|
||||
of allowed IPs by using CIDR notation).
|
||||
of allowed IPs by using CIDR notation). Required.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@@ -661,7 +661,7 @@ spec:
|
||||
ipAllowList:
|
||||
description: |-
|
||||
IPAllowList holds the IP allowlist middleware configuration.
|
||||
This middleware accepts / refuses requests based on the client IP.
|
||||
This middleware limits allowed requests based on the client IP.
|
||||
More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/ipallowlist/
|
||||
properties:
|
||||
ipStrategy:
|
||||
@@ -715,7 +715,7 @@ spec:
|
||||
type: object
|
||||
sourceRange:
|
||||
description: SourceRange defines the set of allowed IPs (or ranges
|
||||
of allowed IPs by using CIDR notation).
|
||||
of allowed IPs by using CIDR notation). Required.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@@ -202,7 +202,7 @@ Duration to keep accepting requests before Traefik initiates the graceful shutdo
|
||||
IdleTimeout is the maximum amount duration an idle (keep-alive) connection will remain idle before closing itself. If zero, no timeout is set. (Default: ```180```)
|
||||
|
||||
`--entrypoints.<name>.transport.respondingtimeouts.readtimeout`:
|
||||
ReadTimeout is the maximum duration for reading the entire request, including the body. If zero, no timeout is set. (Default: ```0```)
|
||||
ReadTimeout is the maximum duration for reading the entire request, including the body. If zero, no timeout is set. (Default: ```60```)
|
||||
|
||||
`--entrypoints.<name>.transport.respondingtimeouts.writetimeout`:
|
||||
WriteTimeout is the maximum duration before timing out writes of the response. If zero, no timeout is set. (Default: ```0```)
|
||||
@@ -729,12 +729,30 @@ Kubernetes certificate authority file path (not needed for in-cluster client).
|
||||
`--providers.kubernetesgateway.endpoint`:
|
||||
Kubernetes server endpoint (required for external cluster client).
|
||||
|
||||
`--providers.kubernetesgateway.experimentalchannel`:
|
||||
Toggles Experimental Channel resources support (TCPRoute, TLSRoute...). (Default: ```false```)
|
||||
|
||||
`--providers.kubernetesgateway.labelselector`:
|
||||
Kubernetes label selector to select specific GatewayClasses.
|
||||
|
||||
`--providers.kubernetesgateway.namespaces`:
|
||||
Kubernetes namespaces.
|
||||
|
||||
`--providers.kubernetesgateway.statusaddress.hostname`:
|
||||
Hostname used for Kubernetes Gateway status address.
|
||||
|
||||
`--providers.kubernetesgateway.statusaddress.ip`:
|
||||
IP used to set Kubernetes Gateway status address.
|
||||
|
||||
`--providers.kubernetesgateway.statusaddress.service`:
|
||||
Published Kubernetes Service to copy status addresses from.
|
||||
|
||||
`--providers.kubernetesgateway.statusaddress.service.name`:
|
||||
Name of the Kubernetes service.
|
||||
|
||||
`--providers.kubernetesgateway.statusaddress.service.namespace`:
|
||||
Namespace of the Kubernetes service.
|
||||
|
||||
`--providers.kubernetesgateway.throttleduration`:
|
||||
Kubernetes refresh throttle duration (Default: ```0```)
|
||||
|
||||
@@ -786,6 +804,9 @@ Kubernetes bearer token (not needed for in-cluster client). It accepts either a
|
||||
`--providers.nomad`:
|
||||
Enable Nomad backend with default settings. (Default: ```false```)
|
||||
|
||||
`--providers.nomad.allowemptyservices`:
|
||||
Allow the creation of services without endpoints. (Default: ```false```)
|
||||
|
||||
`--providers.nomad.constraints`:
|
||||
Constraints is an expression that Traefik matches against the Nomad service's tags to determine whether to create route(s) for that service.
|
||||
|
||||
|
@@ -202,7 +202,7 @@ Duration to keep accepting requests before Traefik initiates the graceful shutdo
|
||||
IdleTimeout is the maximum amount duration an idle (keep-alive) connection will remain idle before closing itself. If zero, no timeout is set. (Default: ```180```)
|
||||
|
||||
`TRAEFIK_ENTRYPOINTS_<NAME>_TRANSPORT_RESPONDINGTIMEOUTS_READTIMEOUT`:
|
||||
ReadTimeout is the maximum duration for reading the entire request, including the body. If zero, no timeout is set. (Default: ```0```)
|
||||
ReadTimeout is the maximum duration for reading the entire request, including the body. If zero, no timeout is set. (Default: ```60```)
|
||||
|
||||
`TRAEFIK_ENTRYPOINTS_<NAME>_TRANSPORT_RESPONDINGTIMEOUTS_WRITETIMEOUT`:
|
||||
WriteTimeout is the maximum duration before timing out writes of the response. If zero, no timeout is set. (Default: ```0```)
|
||||
@@ -729,12 +729,30 @@ Kubernetes certificate authority file path (not needed for in-cluster client).
|
||||
`TRAEFIK_PROVIDERS_KUBERNETESGATEWAY_ENDPOINT`:
|
||||
Kubernetes server endpoint (required for external cluster client).
|
||||
|
||||
`TRAEFIK_PROVIDERS_KUBERNETESGATEWAY_EXPERIMENTALCHANNEL`:
|
||||
Toggles Experimental Channel resources support (TCPRoute, TLSRoute...). (Default: ```false```)
|
||||
|
||||
`TRAEFIK_PROVIDERS_KUBERNETESGATEWAY_LABELSELECTOR`:
|
||||
Kubernetes label selector to select specific GatewayClasses.
|
||||
|
||||
`TRAEFIK_PROVIDERS_KUBERNETESGATEWAY_NAMESPACES`:
|
||||
Kubernetes namespaces.
|
||||
|
||||
`TRAEFIK_PROVIDERS_KUBERNETESGATEWAY_STATUSADDRESS_HOSTNAME`:
|
||||
Hostname used for Kubernetes Gateway status address.
|
||||
|
||||
`TRAEFIK_PROVIDERS_KUBERNETESGATEWAY_STATUSADDRESS_IP`:
|
||||
IP used to set Kubernetes Gateway status address.
|
||||
|
||||
`TRAEFIK_PROVIDERS_KUBERNETESGATEWAY_STATUSADDRESS_SERVICE`:
|
||||
Published Kubernetes Service to copy status addresses from.
|
||||
|
||||
`TRAEFIK_PROVIDERS_KUBERNETESGATEWAY_STATUSADDRESS_SERVICE_NAME`:
|
||||
Name of the Kubernetes service.
|
||||
|
||||
`TRAEFIK_PROVIDERS_KUBERNETESGATEWAY_STATUSADDRESS_SERVICE_NAMESPACE`:
|
||||
Namespace of the Kubernetes service.
|
||||
|
||||
`TRAEFIK_PROVIDERS_KUBERNETESGATEWAY_THROTTLEDURATION`:
|
||||
Kubernetes refresh throttle duration (Default: ```0```)
|
||||
|
||||
@@ -786,6 +804,9 @@ Kubernetes bearer token (not needed for in-cluster client). It accepts either a
|
||||
`TRAEFIK_PROVIDERS_NOMAD`:
|
||||
Enable Nomad backend with default settings. (Default: ```false```)
|
||||
|
||||
`TRAEFIK_PROVIDERS_NOMAD_ALLOWEMPTYSERVICES`:
|
||||
Allow the creation of services without endpoints. (Default: ```false```)
|
||||
|
||||
`TRAEFIK_PROVIDERS_NOMAD_CONSTRAINTS`:
|
||||
Constraints is an expression that Traefik matches against the Nomad service's tags to determine whether to create route(s) for that service.
|
||||
|
||||
|
@@ -146,6 +146,13 @@
|
||||
namespaces = ["foobar", "foobar"]
|
||||
labelSelector = "foobar"
|
||||
throttleDuration = "42s"
|
||||
experimentalChannel = true
|
||||
[providers.kubernetesGateway.statusAddress]
|
||||
ip = "foobar"
|
||||
hostname = "foobar"
|
||||
[providers.kubernetesGateway.statusAddress.service]
|
||||
name = "foobar"
|
||||
namespace = "foobar"
|
||||
[providers.rest]
|
||||
insecure = true
|
||||
[providers.consulCatalog]
|
||||
@@ -184,6 +191,7 @@
|
||||
stale = true
|
||||
exposedByDefault = true
|
||||
refreshInterval = "42s"
|
||||
allowEmptyServices = true
|
||||
namespaces = ["foobar", "foobar"]
|
||||
[providers.nomad.endpoint]
|
||||
address = "foobar"
|
||||
|
@@ -163,6 +163,13 @@ providers:
|
||||
- foobar
|
||||
labelSelector: foobar
|
||||
throttleDuration: 42s
|
||||
experimentalChannel: true
|
||||
statusAddress:
|
||||
ip: foobar
|
||||
hostname: foobar
|
||||
service:
|
||||
name: foobar
|
||||
namespace: foobar
|
||||
rest:
|
||||
insecure: true
|
||||
consulCatalog:
|
||||
@@ -215,6 +222,7 @@ providers:
|
||||
stale: true
|
||||
exposedByDefault: true
|
||||
refreshInterval: 42s
|
||||
allowEmptyServices: true
|
||||
namespaces:
|
||||
- foobar
|
||||
- foobar
|
||||
|
@@ -509,13 +509,14 @@ Setting them has no effect for UDP entryPoints.
|
||||
|
||||
??? info "`transport.respondingTimeouts.readTimeout`"
|
||||
|
||||
_Optional, Default=0s_
|
||||
_Optional, Default=60s_
|
||||
|
||||
`readTimeout` is the maximum duration for reading the entire request, including the body.
|
||||
|
||||
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).
|
||||
If no units are provided, the value is parsed assuming seconds.
|
||||
We strongly suggest to adapt this value accordingly to the your needs.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
## Static configuration
|
||||
|
@@ -373,7 +373,7 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne
|
||||
| [4] | `routes[n].priority` | Defines the [priority](../routers/index.md#priority) to disambiguate rules of the same length, for route matching |
|
||||
| [5] | `routes[n].middlewares` | List of reference to [Middleware](#kind-middleware) |
|
||||
| [6] | `middlewares[n].name` | Defines the [Middleware](#kind-middleware) name |
|
||||
| [7] | `middlewares[n].namespace` | Defines the [Middleware](#kind-middleware) namespace |
|
||||
| [7] | `middlewares[n].namespace` | Defines the [Middleware](#kind-middleware) namespace. It can be omitted when the Middleware is in the IngressRoute namespace. |
|
||||
| [8] | `routes[n].services` | List of any combination of [TraefikService](#kind-traefikservice) and reference to a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) (See below for `ExternalName Service` setup) |
|
||||
| [9] | `services[n].port` | Defines the port of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/). This can be a reference to a named port. |
|
||||
| [10] | `services[n].serversTransport` | Defines the reference to a [ServersTransport](#kind-serverstransport). The ServersTransport namespace is assumed to be the [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) namespace (see [ServersTransport reference](#serverstransport-reference)). |
|
||||
|
@@ -241,29 +241,61 @@ Kubernetes cluster before creating `HTTPRoute` objects.
|
||||
- name: api@internal
|
||||
group: traefik.io # [18]
|
||||
kind: TraefikService # [19]
|
||||
- filters: # [20]
|
||||
- type: ExtensionRef # [21]
|
||||
extensionRef: # [22]
|
||||
group: traefik.io # [23]
|
||||
kind: Middleware # [24]
|
||||
name: my-middleware # [25]
|
||||
- type: RequestRedirect # [26]
|
||||
requestRedirect: # [27]
|
||||
scheme: https # [28]
|
||||
statusCode: 301 # [29]
|
||||
- type: RequestHeaderModifier # [30]
|
||||
requestHeaderModifier: # [31]
|
||||
set:
|
||||
- name: X-Foo
|
||||
value: Bar
|
||||
add:
|
||||
- name: X-Bar
|
||||
value: Foo
|
||||
remove:
|
||||
- X-Baz
|
||||
```
|
||||
|
||||
| Ref | Attribute | Description |
|
||||
|------|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [1] | `parentRefs` | References the resources (usually Gateways) that a Route wants to be attached to. |
|
||||
| [2] | `name` | Name of the referent. |
|
||||
| [3] | `namespace` | Namespace of the referent. When unspecified (or empty string), this refers to the local namespace of the Route. |
|
||||
| [4] | `sectionName` | Name of a section within the target resource (the Listener name). |
|
||||
| [5] | `hostnames` | A set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request. |
|
||||
| [6] | `rules` | A list of HTTP matchers, filters and actions. |
|
||||
| [7] | `matches` | Conditions used for matching the rule against incoming HTTP requests. Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied. |
|
||||
| [8] | `path` | An HTTP request path matcher. If this field is not specified, a default prefix match on the "/" path is provided. |
|
||||
| [9] | `type` | Type of match against the path Value (supported types: `Exact`, `Prefix`). |
|
||||
| [10] | `value` | The value of the HTTP path to match against. |
|
||||
| [11] | `headers` | Conditions to select a HTTP route by matching HTTP request headers. |
|
||||
| [12] | `type` | Type of match for the HTTP request header match against the `values` (supported types: `Exact`). |
|
||||
| [13] | `value` | A map of HTTP Headers to be matched. It MUST contain at least one entry. |
|
||||
| [14] | `backendRefs` | Defines the backend(s) where matching requests should be sent. |
|
||||
| [15] | `name` | The name of the referent service. |
|
||||
| [16] | `weight` | The proportion of traffic forwarded to a targetRef, computed as weight/(sum of all weights in targetRefs). |
|
||||
| [17] | `port` | The port of the referent service. |
|
||||
| [18] | `group` | Group is the group of the referent. Only `traefik.io` and `gateway.networking.k8s.io` values are supported. |
|
||||
| [19] | `kind` | Kind is kind of the referent. Only `TraefikService` and `Service` values are supported. |
|
||||
| Ref | Attribute | Description |
|
||||
|------|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [1] | `parentRefs` | References the resources (usually Gateways) that a Route wants to be attached to. |
|
||||
| [2] | `name` | Name of the referent. |
|
||||
| [3] | `namespace` | Namespace of the referent. When unspecified (or empty string), this refers to the local namespace of the Route. |
|
||||
| [4] | `sectionName` | Name of a section within the target resource (the Listener name). |
|
||||
| [5] | `hostnames` | A set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request. |
|
||||
| [6] | `rules` | A list of HTTP matchers, filters and actions. |
|
||||
| [7] | `matches` | Conditions used for matching the rule against incoming HTTP requests. Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied. |
|
||||
| [8] | `path` | An HTTP request path matcher. If this field is not specified, a default prefix match on the "/" path is provided. |
|
||||
| [9] | `type` | Type of match against the path Value (supported types: `Exact`, `Prefix`). |
|
||||
| [10] | `value` | The value of the HTTP path to match against. |
|
||||
| [11] | `headers` | Conditions to select a HTTP route by matching HTTP request headers. |
|
||||
| [12] | `name` | Name of the HTTP header to be matched. |
|
||||
| [13] | `value` | Value of HTTP Header to be matched. |
|
||||
| [14] | `backendRefs` | Defines the backend(s) where matching requests should be sent. |
|
||||
| [15] | `name` | The name of the referent service. |
|
||||
| [16] | `weight` | The proportion of traffic forwarded to a targetRef, computed as weight/(sum of all weights in targetRefs). |
|
||||
| [17] | `port` | The port of the referent service. |
|
||||
| [18] | `group` | Group is the group of the referent. Only `traefik.io` and `gateway.networking.k8s.io` values are supported. |
|
||||
| [19] | `kind` | Kind is kind of the referent. Only `TraefikService` and `Service` values are supported. |
|
||||
| [20] | `filters` | Defines the filters (middlewares) applied to the route. |
|
||||
| [21] | `type` | Defines the type of filter; ExtensionRef is used for configuring custom HTTP filters. |
|
||||
| [22] | `extensionRef` | Configuration of the custom HTTP filter. |
|
||||
| [23] | `group` | Group of the kubernetes object to reference. |
|
||||
| [24] | `kind` | Kind of the kubernetes object to reference. |
|
||||
| [25] | `name` | Name of the kubernetes object to reference. |
|
||||
| [26] | `type` | Defines the type of filter; RequestRedirect redirects a request to another location. |
|
||||
| [27] | `requestRedirect` | Configuration of redirect filter. |
|
||||
| [28] | `scheme` | Scheme is the scheme to be used in the value of the Location header in the response. |
|
||||
| [29] | `statusCode` | StatusCode is the HTTP status code to be used in response. |
|
||||
| [30] | `type` | Defines the type of filter; RequestHeaderModifier modifies request headers. |
|
||||
| [31] | `requestHeaderModifier` | Configuration of RequestHeaderModifier filter. |
|
||||
|
||||
### Kind: `TCPRoute`
|
||||
|
||||
|
@@ -442,6 +442,14 @@ The priority is directly equal to the length of the rule, and so the longest len
|
||||
|
||||
A value of `0` for the priority is ignored: `priority = 0` means that the default rules length sorting is used.
|
||||
|
||||
??? warning "Maximum Value"
|
||||
|
||||
Traefik reserves a range of priorities for its internal routers,
|
||||
the maximum user-defined router priority value is:
|
||||
|
||||
- `(MaxInt32 - 1000)` for 32-bit platforms,
|
||||
- `(MaxInt64 - 1000)` for 64-bit platforms.
|
||||
|
||||
??? info "How default priorities are computed"
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
@@ -1148,6 +1156,14 @@ The priority is directly equal to the length of the rule, and so the longest len
|
||||
|
||||
A value of `0` for the priority is ignored: `priority = 0` means that the default rules length sorting is used.
|
||||
|
||||
??? warning "Maximum Value"
|
||||
|
||||
Traefik reserves a range of priorities for its internal routers,
|
||||
the maximum user-defined router priority value is:
|
||||
|
||||
- `(MaxInt32 - 1000)` for 32-bit platforms,
|
||||
- `(MaxInt64 - 1000)` for 64-bit platforms.
|
||||
|
||||
??? info "How default priorities are computed"
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
|
28
go.mod
28
go.mod
@@ -12,8 +12,8 @@ require (
|
||||
github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
|
||||
github.com/docker/cli v24.0.7+incompatible
|
||||
github.com/docker/docker v24.0.7+incompatible
|
||||
github.com/docker/cli v24.0.9+incompatible
|
||||
github.com/docker/docker v24.0.9+incompatible
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/fatih/structs v1.1.0
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
@@ -49,7 +49,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
|
||||
github.com/prometheus/client_golang v1.17.0
|
||||
github.com/prometheus/client_model v0.5.0
|
||||
github.com/quic-go/quic-go v0.40.1
|
||||
github.com/quic-go/quic-go v0.42.0
|
||||
github.com/rs/zerolog v1.29.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spiffe/go-spiffe/v2 v2.1.1
|
||||
@@ -61,7 +61,7 @@ require (
|
||||
github.com/tidwall/gjson v1.17.0
|
||||
github.com/traefik/grpc-web v0.16.0
|
||||
github.com/traefik/paerser v0.2.0
|
||||
github.com/traefik/yaegi v0.15.1
|
||||
github.com/traefik/yaegi v0.16.1
|
||||
github.com/unrolled/render v1.0.2
|
||||
github.com/unrolled/secure v1.0.9
|
||||
github.com/vulcand/oxy/v2 v2.0.0-20230427132221-be5cf38f3c1c
|
||||
@@ -79,12 +79,12 @@ require (
|
||||
go.opentelemetry.io/otel/sdk/metric v1.24.0
|
||||
go.opentelemetry.io/otel/trace v1.24.0
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
|
||||
golang.org/x/mod v0.14.0
|
||||
golang.org/x/net v0.20.0
|
||||
golang.org/x/sys v0.17.0
|
||||
golang.org/x/mod v0.17.0
|
||||
golang.org/x/net v0.24.0
|
||||
golang.org/x/sys v0.19.0
|
||||
golang.org/x/text v0.14.0
|
||||
golang.org/x/time v0.5.0
|
||||
golang.org/x/tools v0.17.0
|
||||
golang.org/x/tools v0.20.0
|
||||
google.golang.org/grpc v1.61.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/api v0.28.4
|
||||
@@ -262,7 +262,7 @@ require (
|
||||
github.com/nrdcg/porkbun v0.3.0 // indirect
|
||||
github.com/nzdjb/go-metaname v1.0.0 // indirect
|
||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.11.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.17.1 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
|
||||
github.com/opencontainers/runc v1.1.7 // indirect
|
||||
@@ -276,7 +276,6 @@ require (
|
||||
github.com/prometheus/common v0.45.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
||||
github.com/redis/go-redis/v9 v9.2.1 // indirect
|
||||
github.com/rs/cors v1.7.0 // indirect
|
||||
github.com/sacloud/api-client-go v0.2.8 // indirect
|
||||
@@ -317,20 +316,21 @@ require (
|
||||
go.opentelemetry.io/contrib/propagators/ot v1.24.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.1.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/mock v0.3.0 // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/ratelimit v0.2.0 // indirect
|
||||
go.uber.org/zap v1.26.0 // indirect
|
||||
golang.org/x/arch v0.4.0 // indirect
|
||||
golang.org/x/crypto v0.19.0 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/oauth2 v0.16.0 // indirect
|
||||
golang.org/x/term v0.17.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/term v0.19.0 // indirect
|
||||
google.golang.org/api v0.149.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect
|
||||
google.golang.org/protobuf v1.32.0 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/h2non/gock.v1 v1.0.16 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
|
62
go.sum
62
go.sum
@@ -265,12 +265,12 @@ github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
|
||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||
github.com/dnsimple/dnsimple-go v1.2.0 h1:ddTGyLVKly5HKb5L65AkLqFqwZlWo3WnR0BlFZlIddM=
|
||||
github.com/dnsimple/dnsimple-go v1.2.0/go.mod h1:z/cs26v/eiRvUyXsHQBLd8lWF8+cD6GbmkPH84plM4U=
|
||||
github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg=
|
||||
github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v24.0.9+incompatible h1:OxbimnP/z+qVjDLpq9wbeFU3Nc30XhSe+LkwYQisD50=
|
||||
github.com/docker/cli v24.0.9+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
|
||||
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM=
|
||||
github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0=
|
||||
github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
@@ -860,16 +860,16 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
|
||||
github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
|
||||
github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8=
|
||||
github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
||||
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
|
||||
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
@@ -961,10 +961,8 @@ github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3c
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/quic-go/quic-go v0.40.1 h1:X3AGzUNFs0jVuO3esAGnTfvdgvL4fq655WaOi1snv1Q=
|
||||
github.com/quic-go/quic-go v0.40.1/go.mod h1:PeN7kuVJ4xZbxSv/4OX6S1USOX8MJvydwpTx31vx60c=
|
||||
github.com/quic-go/quic-go v0.42.0 h1:uSfdap0eveIl8KXnipv9K7nlwZ5IqLlYOpJ58u5utpM=
|
||||
github.com/quic-go/quic-go v0.42.0/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg=
|
||||
github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
@@ -1097,8 +1095,8 @@ github.com/traefik/grpc-web v0.16.0 h1:eeUWZaFg6ZU0I9dWOYE2D5qkNzRBmXzzuRlxdltas
|
||||
github.com/traefik/grpc-web v0.16.0/go.mod h1:2ttniSv7pTgBWIU2HZLokxRfFX3SA60c/DTmQQgVml4=
|
||||
github.com/traefik/paerser v0.2.0 h1:zqCLGSXoNlcBd+mzqSCLjon/I6phqIjeJL2xFB2ysgQ=
|
||||
github.com/traefik/paerser v0.2.0/go.mod h1:afzaVcgF8A+MpTnPG4wBr4whjanCSYA6vK5RwaYVtRc=
|
||||
github.com/traefik/yaegi v0.15.1 h1:YA5SbaL6HZA0Exh9T/oArRHqGN2HQ+zgmCY7dkoTXu4=
|
||||
github.com/traefik/yaegi v0.15.1/go.mod h1:AVRxhaI2G+nUsaM1zyktzwXn69G3t/AuTDrCiTds9p0=
|
||||
github.com/traefik/yaegi v0.16.1 h1:f1De3DVJqIDKmnasUF6MwmWv1dSEEat0wcpXhD2On3E=
|
||||
github.com/traefik/yaegi v0.16.1/go.mod h1:4eVhbPb3LnD2VigQjhYbEJ69vDRFdT2HQNrXx8eEwUY=
|
||||
github.com/transip/gotransip/v6 v6.23.0 h1:PsTdjortrEZ8IFFifEryzjVjOy9SgK4ahlnhKBBIQgA=
|
||||
github.com/transip/gotransip/v6 v6.23.0/go.mod h1:nzv9eN2tdsUrm5nG5ZX6AugYIU4qgsMwIn2c0EZLk8c=
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
@@ -1207,8 +1205,8 @@ go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
|
||||
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
@@ -1247,8 +1245,8 @@ golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@@ -1280,8 +1278,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -1323,8 +1321,8 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -1342,8 +1340,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1417,8 +1415,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@@ -1427,8 +1425,8 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
|
||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
@@ -1488,8 +1486,8 @@ golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
|
||||
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -1573,8 +1571,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
@@ -1303,7 +1303,7 @@ spec:
|
||||
ipAllowList:
|
||||
description: |-
|
||||
IPAllowList holds the IP allowlist middleware configuration.
|
||||
This middleware accepts / refuses requests based on the client IP.
|
||||
This middleware limits allowed requests based on the client IP.
|
||||
More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/ipallowlist/
|
||||
properties:
|
||||
ipStrategy:
|
||||
@@ -1357,7 +1357,7 @@ spec:
|
||||
type: object
|
||||
sourceRange:
|
||||
description: SourceRange defines the set of allowed IPs (or ranges
|
||||
of allowed IPs by using CIDR notation).
|
||||
of allowed IPs by using CIDR notation). Required.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@@ -27,3 +27,4 @@
|
||||
address = ":8443"
|
||||
|
||||
[providers.kubernetesGateway]
|
||||
experimentalChannel = true
|
||||
|
@@ -24,10 +24,12 @@
|
||||
[tcp.routers.router1]
|
||||
service = "service1"
|
||||
rule = "HostSNI(`snitest.net`)"
|
||||
[tcp.routers.router1.tls]
|
||||
|
||||
[tcp.routers.router2]
|
||||
service = "service2"
|
||||
rule = "HostSNI(`snitest.com`)"
|
||||
[tcp.routers.router2.tls]
|
||||
|
||||
[tcp.services]
|
||||
[tcp.services.service1]
|
||||
|
@@ -1134,8 +1134,6 @@ func (s *HTTPSSuite) TestWithDomainFronting() {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "https://127.0.0.1:4443", nil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = test.hostHeader
|
||||
@@ -1179,8 +1177,6 @@ func (s *HTTPSSuite) TestWithInvalidTLSOption() {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
|
||||
tlsConfig := &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
|
@@ -207,7 +207,13 @@ func clean(element any) {
|
||||
|
||||
var svcFieldNames []string
|
||||
for i := range valueSvcRoot.NumField() {
|
||||
svcFieldNames = append(svcFieldNames, valueSvcRoot.Type().Field(i).Name)
|
||||
field := valueSvcRoot.Type().Field(i)
|
||||
// do not create empty node for hidden config.
|
||||
if field.Tag.Get("file") == "-" && field.Tag.Get("kv") == "-" && field.Tag.Get("label") == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
svcFieldNames = append(svcFieldNames, field.Name)
|
||||
}
|
||||
|
||||
sort.Strings(svcFieldNames)
|
||||
|
@@ -39,7 +39,7 @@ func Append(router *mux.Router, customAssets fs.FS) {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
|
||||
w.Header().Del("Content-Type")
|
||||
|
||||
http.StripPrefix("/dashboard/", http.FileServer(http.FS(assets))).ServeHTTP(w, r)
|
||||
http.StripPrefix("/dashboard/", http.FileServerFS(assets)).ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ func (g Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
|
||||
w.Header().Del("Content-Type")
|
||||
|
||||
http.FileServer(http.FS(assets)).ServeHTTP(w, r)
|
||||
http.FileServerFS(assets).ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
func safePrefix(req *http.Request) string {
|
||||
|
@@ -42,7 +42,6 @@ func Test_safePrefix(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -91,7 +90,6 @@ func Test_ContentSecurityPolicy(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -210,7 +210,6 @@ func TestHandler_EntryPoints(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -998,7 +998,6 @@ func TestHandler_HTTP(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -269,7 +269,6 @@ func TestHandler_Overview(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -874,7 +874,6 @@ func TestHandler_TCP(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -127,7 +127,6 @@ func TestHandler_RawData(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -252,7 +251,6 @@ func TestHandler_GetMiddleware(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -564,7 +564,6 @@ func TestHandler_UDP(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -828,7 +828,6 @@ func TestSortRouters(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(fmt.Sprintf("%s-%s", test.direction, test.sortBy), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -1339,7 +1338,6 @@ func TestSortServices(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(fmt.Sprintf("%s-%s", test.direction, test.sortBy), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -1674,7 +1672,6 @@ func TestSortMiddlewares(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(fmt.Sprintf("%s-%s", test.direction, test.sortBy), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -267,7 +267,6 @@ func TestDeprecationNotice(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -385,7 +384,6 @@ func TestLoad(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
tconfig := cmd.NewTraefikConfiguration()
|
||||
c := &cli.Command{Configuration: tconfig}
|
||||
|
@@ -65,7 +65,7 @@ func createBody(staticConfiguration *static.Configuration) (*bytes.Buffer, error
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err = json.NewEncoder(buf).Encode(data) //nolint:musttag // cannot be changed for historical reasons.
|
||||
err = json.NewEncoder(buf).Encode(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -39,6 +39,9 @@ type Middleware struct {
|
||||
GrpcWeb *GrpcWeb `json:"grpcWeb,omitempty" toml:"grpcWeb,omitempty" yaml:"grpcWeb,omitempty" export:"true"`
|
||||
|
||||
Plugin map[string]PluginConf `json:"plugin,omitempty" toml:"plugin,omitempty" yaml:"plugin,omitempty" export:"true"`
|
||||
|
||||
// Gateway API HTTPRoute filters middlewares.
|
||||
RequestHeaderModifier *RequestHeaderModifier `json:"requestHeaderModifier,omitempty" toml:"-" yaml:"-" label:"-" file:"-" kv:"-" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
@@ -420,11 +423,11 @@ func (s *IPStrategy) Get() (ip.Strategy, error) {
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// IPWhiteList holds the IP whitelist middleware configuration.
|
||||
// This middleware accepts / refuses requests based on the client IP.
|
||||
// This middleware limits allowed requests based on the client IP.
|
||||
// More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/ipwhitelist/
|
||||
// Deprecated: please use IPAllowList instead.
|
||||
type IPWhiteList struct {
|
||||
// SourceRange defines the set of allowed IPs (or ranges of allowed IPs by using CIDR notation).
|
||||
// SourceRange defines the set of allowed IPs (or ranges of allowed IPs by using CIDR notation). Required.
|
||||
SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"`
|
||||
IPStrategy *IPStrategy `json:"ipStrategy,omitempty" toml:"ipStrategy,omitempty" yaml:"ipStrategy,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"`
|
||||
}
|
||||
@@ -432,7 +435,7 @@ type IPWhiteList struct {
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// IPAllowList holds the IP allowlist middleware configuration.
|
||||
// This middleware accepts / refuses requests based on the client IP.
|
||||
// This middleware limits allowed requests based on the client IP.
|
||||
// More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/ipallowlist/
|
||||
type IPAllowList struct {
|
||||
// SourceRange defines the set of allowed IPs (or ranges of allowed IPs by using CIDR notation).
|
||||
@@ -673,3 +676,12 @@ type TLSClientCertificateSubjectDNInfo struct {
|
||||
|
||||
// Users holds a list of users.
|
||||
type Users []string
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// RequestHeaderModifier holds the request header modifier configuration.
|
||||
type RequestHeaderModifier struct {
|
||||
Set map[string]string `json:"set,omitempty"`
|
||||
Add map[string]string `json:"add,omitempty"`
|
||||
Remove []string `json:"remove,omitempty"`
|
||||
}
|
||||
|
@@ -34,6 +34,8 @@ type TCPIPWhiteList struct {
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// TCPIPAllowList holds the TCP IPAllowList middleware configuration.
|
||||
// This middleware limits allowed requests based on the client IP.
|
||||
// More info: https://doc.traefik.io/traefik/v3.0/middlewares/tcp/ipallowlist/
|
||||
type TCPIPAllowList struct {
|
||||
// SourceRange defines the allowed IPs (or ranges of allowed IPs by using CIDR notation).
|
||||
SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"`
|
||||
|
@@ -859,6 +859,11 @@ func (in *Middleware) DeepCopyInto(out *Middleware) {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
}
|
||||
if in.RequestHeaderModifier != nil {
|
||||
in, out := &in.RequestHeaderModifier, &out.RequestHeaderModifier
|
||||
*out = new(RequestHeaderModifier)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1067,6 +1072,41 @@ func (in *ReplacePathRegex) DeepCopy() *ReplacePathRegex {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RequestHeaderModifier) DeepCopyInto(out *RequestHeaderModifier) {
|
||||
*out = *in
|
||||
if in.Set != nil {
|
||||
in, out := &in.Set, &out.Set
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.Add != nil {
|
||||
in, out := &in.Add, &out.Add
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.Remove != nil {
|
||||
in, out := &in.Remove, &out.Remove
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RequestHeaderModifier.
|
||||
func (in *RequestHeaderModifier) DeepCopy() *RequestHeaderModifier {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RequestHeaderModifier)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ResponseForwarding) DeepCopyInto(out *ResponseForwarding) {
|
||||
*out = *in
|
||||
|
@@ -244,7 +244,6 @@ func TestDecodeToNode(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -87,7 +87,6 @@ func TestDecode(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -208,7 +208,6 @@ func TestGetRoutersByEntryPoints(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runtimeConfig := NewConfig(test.conf)
|
||||
|
@@ -208,7 +208,6 @@ func TestGetTCPRoutersByEntryPoints(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runtimeConfig := NewConfig(test.conf)
|
||||
|
@@ -665,8 +665,6 @@ func TestPopulateUsedBy(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -189,7 +189,6 @@ func TestGetUDPRoutersByEntryPoints(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runtimeConfig := NewConfig(test.conf)
|
||||
|
@@ -42,6 +42,9 @@ const (
|
||||
// DefaultIdleTimeout before closing an idle connection.
|
||||
DefaultIdleTimeout = 180 * time.Second
|
||||
|
||||
// DefaultReadTimeout defines the default maximum duration for reading the entire request, including the body.
|
||||
DefaultReadTimeout = 60 * time.Second
|
||||
|
||||
// DefaultAcmeCAServer is the default ACME API endpoint.
|
||||
DefaultAcmeCAServer = "https://acme-v02.api.letsencrypt.org/directory"
|
||||
|
||||
@@ -164,6 +167,7 @@ type RespondingTimeouts struct {
|
||||
|
||||
// SetDefaults sets the default values.
|
||||
func (a *RespondingTimeouts) SetDefaults() {
|
||||
a.ReadTimeout = ptypes.Duration(DefaultReadTimeout)
|
||||
a.IdleTimeout = ptypes.Duration(DefaultIdleTimeout)
|
||||
}
|
||||
|
||||
@@ -288,6 +292,10 @@ func (c *Configuration) SetEffectiveConfiguration() {
|
||||
entryPoints[epName] = gateway.Entrypoint{Address: entryPoint.GetAddress(), HasHTTPTLSConf: entryPoint.HTTP.TLS != nil}
|
||||
}
|
||||
|
||||
if c.Providers.KubernetesCRD != nil {
|
||||
c.Providers.KubernetesCRD.FillExtensionBuilderRegistry(c.Providers.KubernetesGateway)
|
||||
}
|
||||
|
||||
c.Providers.KubernetesGateway.EntryPoints = entryPoints
|
||||
}
|
||||
|
||||
|
@@ -26,7 +26,6 @@ func TestHasEntrypoint(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -243,7 +243,6 @@ func TestServiceHealthChecker_newRequest(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -405,7 +404,6 @@ func TestServiceHealthChecker_Launch(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -36,7 +36,6 @@ func TestIsAuthorized(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -117,7 +116,6 @@ func TestNew(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -289,7 +287,6 @@ func TestContainsIsAllowed(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -21,7 +21,6 @@ func TestRemoteAddrStrategy_GetIP(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -61,7 +60,6 @@ func TestDepthStrategy_GetIP(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -109,7 +107,6 @@ func TestTrustedIPsStrategy_GetIP(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -67,7 +67,6 @@ func TestDatadog_parseDatadogAddress(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -89,8 +89,6 @@ func TestOpenTelemetry_labels(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -181,8 +179,6 @@ func TestOpenTelemetry_GaugeCollectorAdd(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -275,8 +271,6 @@ func TestOpenTelemetry_GaugeCollectorSet(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -64,7 +64,6 @@ func TestRegisterPromState(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
actualNbRegistries := 0
|
||||
for _, prom := range test.prometheusSlice {
|
||||
@@ -381,7 +380,6 @@ func TestPrometheus(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
family := findMetricFamily(test.name, metricsFamilies)
|
||||
if family == nil {
|
||||
|
@@ -86,7 +86,6 @@ func TestCommonLogFormatter_Format(t *testing.T) {
|
||||
t.Setenv("TZ", "Etc/GMT+9")
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -150,7 +149,6 @@ func Test_toLog(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -180,7 +180,6 @@ func TestLoggerHeaderFields(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
logFile, err := os.CreateTemp(t.TempDir(), "*.log")
|
||||
require.NoError(t, err)
|
||||
@@ -469,7 +468,6 @@ func TestLoggerJSON(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -687,7 +685,6 @@ func TestNewLogHandlerOutputStdout(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
// NOTE: It is not possible to run these cases in parallel because we capture Stdout
|
||||
|
||||
|
@@ -60,7 +60,6 @@ func TestParseAccessLog(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -28,8 +28,6 @@ func TestSaveRetries(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
|
||||
t.Run(fmt.Sprintf("%d retries", test.requestAttempt), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
saveRetries := &SaveRetries{}
|
||||
|
@@ -29,7 +29,6 @@ func TestNewAddPrefix(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -75,7 +74,6 @@ func TestAddPrefix(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -210,7 +210,6 @@ func TestBasicAuthUsersFromFile(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -88,7 +88,6 @@ func TestDigestAuthUsersFromFile(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -48,7 +48,6 @@ func TestBuffering(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -88,7 +88,6 @@ func Test_NoBody(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -347,7 +346,6 @@ func Test_ExcludedContentTypes(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -452,7 +450,6 @@ func Test_IncludedContentTypes(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -557,7 +554,6 @@ func Test_FlushExcludedContentTypes(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -676,7 +672,6 @@ func Test_FlushIncludedContentTypes(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -831,8 +826,6 @@ func TestParseContentType_equals(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -74,8 +74,6 @@ func TestNegotiation(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -299,7 +297,6 @@ func TestShouldNotCompressWhenSpecificContentType(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -351,7 +348,6 @@ func TestShouldCompressWhenSpecificContentType(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -547,8 +543,6 @@ func TestMinResponseBodyBytes(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -47,7 +47,6 @@ func TestRemover(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -46,7 +46,6 @@ func TestAutoDetection(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -157,7 +157,6 @@ func TestHandler(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -272,7 +272,6 @@ func TestServeHTTP(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -369,7 +368,6 @@ func Test_isWebsocketRequest(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
56
pkg/middlewares/headermodifier/request_header_modifier.go
Normal file
56
pkg/middlewares/headermodifier/request_header_modifier.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package headermodifier
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/traefik/traefik/v3/pkg/config/dynamic"
|
||||
"github.com/traefik/traefik/v3/pkg/middlewares"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
const typeName = "RequestHeaderModifier"
|
||||
|
||||
// requestHeaderModifier is a middleware used to modify the headers of an HTTP request.
|
||||
type requestHeaderModifier struct {
|
||||
next http.Handler
|
||||
name string
|
||||
|
||||
set map[string]string
|
||||
add map[string]string
|
||||
remove []string
|
||||
}
|
||||
|
||||
// NewRequestHeaderModifier creates a new request header modifier middleware.
|
||||
func NewRequestHeaderModifier(ctx context.Context, next http.Handler, config dynamic.RequestHeaderModifier, name string) (http.Handler, error) {
|
||||
logger := middlewares.GetLogger(ctx, name, typeName)
|
||||
logger.Debug().Msg("Creating middleware")
|
||||
|
||||
return &requestHeaderModifier{
|
||||
next: next,
|
||||
name: name,
|
||||
set: config.Set,
|
||||
add: config.Add,
|
||||
remove: config.Remove,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *requestHeaderModifier) GetTracingInformation() (string, string, trace.SpanKind) {
|
||||
return r.name, typeName, trace.SpanKindUnspecified
|
||||
}
|
||||
|
||||
func (r *requestHeaderModifier) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
for headerName, headerValue := range r.set {
|
||||
req.Header.Set(headerName, headerValue)
|
||||
}
|
||||
|
||||
for headerName, headerValue := range r.add {
|
||||
req.Header.Add(headerName, headerValue)
|
||||
}
|
||||
|
||||
for _, headerName := range r.remove {
|
||||
req.Header.Del(headerName)
|
||||
}
|
||||
|
||||
r.next.ServeHTTP(rw, req)
|
||||
}
|
121
pkg/middlewares/headermodifier/request_header_modifier_test.go
Normal file
121
pkg/middlewares/headermodifier/request_header_modifier_test.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package headermodifier
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/traefik/traefik/v3/pkg/config/dynamic"
|
||||
"github.com/traefik/traefik/v3/pkg/testhelpers"
|
||||
)
|
||||
|
||||
func TestRequestHeaderModifier(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
config dynamic.RequestHeaderModifier
|
||||
requestHeaders http.Header
|
||||
expectedHeaders http.Header
|
||||
}{
|
||||
{
|
||||
desc: "no config",
|
||||
config: dynamic.RequestHeaderModifier{},
|
||||
expectedHeaders: map[string][]string{},
|
||||
},
|
||||
{
|
||||
desc: "set header",
|
||||
config: dynamic.RequestHeaderModifier{
|
||||
Set: map[string]string{"Foo": "Bar"},
|
||||
},
|
||||
expectedHeaders: map[string][]string{"Foo": {"Bar"}},
|
||||
},
|
||||
{
|
||||
desc: "set header with existing headers",
|
||||
config: dynamic.RequestHeaderModifier{
|
||||
Set: map[string]string{"Foo": "Bar"},
|
||||
},
|
||||
requestHeaders: map[string][]string{"Foo": {"Baz"}, "Bar": {"Foo"}},
|
||||
expectedHeaders: map[string][]string{"Foo": {"Bar"}, "Bar": {"Foo"}},
|
||||
},
|
||||
{
|
||||
desc: "set multiple headers with existing headers",
|
||||
config: dynamic.RequestHeaderModifier{
|
||||
Set: map[string]string{"Foo": "Bar", "Bar": "Foo"},
|
||||
},
|
||||
requestHeaders: map[string][]string{"Foo": {"Baz"}, "Bar": {"Foobar"}},
|
||||
expectedHeaders: map[string][]string{"Foo": {"Bar"}, "Bar": {"Foo"}},
|
||||
},
|
||||
{
|
||||
desc: "add header",
|
||||
config: dynamic.RequestHeaderModifier{
|
||||
Add: map[string]string{"Foo": "Bar"},
|
||||
},
|
||||
expectedHeaders: map[string][]string{"Foo": {"Bar"}},
|
||||
},
|
||||
{
|
||||
desc: "add header with existing headers",
|
||||
config: dynamic.RequestHeaderModifier{
|
||||
Add: map[string]string{"Foo": "Bar"},
|
||||
},
|
||||
requestHeaders: map[string][]string{"Foo": {"Baz"}, "Bar": {"Foo"}},
|
||||
expectedHeaders: map[string][]string{"Foo": {"Baz", "Bar"}, "Bar": {"Foo"}},
|
||||
},
|
||||
{
|
||||
desc: "add multiple headers with existing headers",
|
||||
config: dynamic.RequestHeaderModifier{
|
||||
Add: map[string]string{"Foo": "Bar", "Bar": "Foo"},
|
||||
},
|
||||
requestHeaders: map[string][]string{"Foo": {"Baz"}, "Bar": {"Foobar"}},
|
||||
expectedHeaders: map[string][]string{"Foo": {"Baz", "Bar"}, "Bar": {"Foobar", "Foo"}},
|
||||
},
|
||||
{
|
||||
desc: "remove header",
|
||||
config: dynamic.RequestHeaderModifier{
|
||||
Remove: []string{"Foo"},
|
||||
},
|
||||
expectedHeaders: map[string][]string{},
|
||||
},
|
||||
{
|
||||
desc: "remove header with existing headers",
|
||||
config: dynamic.RequestHeaderModifier{
|
||||
Remove: []string{"Foo"},
|
||||
},
|
||||
requestHeaders: map[string][]string{"Foo": {"Baz"}, "Bar": {"Foo"}},
|
||||
expectedHeaders: map[string][]string{"Bar": {"Foo"}},
|
||||
},
|
||||
{
|
||||
desc: "remove multiple headers with existing headers",
|
||||
config: dynamic.RequestHeaderModifier{
|
||||
Remove: []string{"Foo", "Bar"},
|
||||
},
|
||||
requestHeaders: map[string][]string{"Foo": {"Bar"}, "Bar": {"Foo"}, "Baz": {"Bar"}},
|
||||
expectedHeaders: map[string][]string{"Baz": {"Bar"}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var gotHeaders http.Header
|
||||
next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
gotHeaders = r.Header
|
||||
})
|
||||
|
||||
handler, err := NewRequestHeaderModifier(context.Background(), next, test.config, "foo-request-header-modifier")
|
||||
require.NoError(t, err)
|
||||
|
||||
req := testhelpers.MustNewRequest(http.MethodGet, "http://localhost", nil)
|
||||
if test.requestHeaders != nil {
|
||||
req.Header = test.requestHeaders
|
||||
}
|
||||
|
||||
resp := httptest.NewRecorder()
|
||||
handler.ServeHTTP(resp, req)
|
||||
|
||||
assert.Equal(t, test.expectedHeaders, gotHeaders)
|
||||
})
|
||||
}
|
||||
}
|
@@ -52,7 +52,6 @@ func TestNewHeader_customRequestHeader(t *testing.T) {
|
||||
emptyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -59,7 +59,6 @@ func TestNew_allowedHosts(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -67,7 +67,6 @@ func Test_newSecure_modifyResponse(t *testing.T) {
|
||||
emptyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -41,7 +41,6 @@ func TestNewIPAllowLister(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -102,7 +101,6 @@ func TestIPAllowLister_ServeHTTP(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -33,7 +33,6 @@ func TestNewIPWhiteLister(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -76,7 +75,6 @@ func TestIPWhiteLister_ServeHTTP(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -80,7 +80,6 @@ func Test_getMethod(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.method, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -132,7 +131,6 @@ func Test_getRequestProtocol(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -175,7 +173,6 @@ func Test_grpcStatusCode(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -122,7 +122,6 @@ func TestEntryPointMiddleware_metrics(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -310,7 +310,6 @@ func TestPassTLSClientCert_PEM(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -533,7 +532,6 @@ func TestPassTLSClientCert_certInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -604,7 +602,6 @@ WqeUSNGYV//RunTeuRDAf5OxehERb1srzBXhRZ3cZdzXbgR/`,
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -645,7 +642,6 @@ func Test_getSANs(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -89,7 +89,6 @@ func TestNewRateLimiter(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -248,7 +247,6 @@ func TestRateLimit(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
if test.loadDuration >= time.Minute && testing.Short() {
|
||||
t.Skip("skipping test in short mode.")
|
||||
|
@@ -154,7 +154,6 @@ func TestRedirectRegexHandler(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -283,8 +283,6 @@ func TestRedirectSchemeHandler(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -52,7 +52,7 @@ func (rp *replacePathRegex) ServeHTTP(rw http.ResponseWriter, req *http.Request)
|
||||
currentPath = req.URL.EscapedPath()
|
||||
}
|
||||
|
||||
if rp.regexp != nil && len(rp.replacement) > 0 && rp.regexp.MatchString(currentPath) {
|
||||
if rp.regexp != nil && rp.regexp.MatchString(currentPath) {
|
||||
req.Header.Add(replacepath.ReplacedPathHeader, currentPath)
|
||||
req.URL.RawPath = rp.regexp.ReplaceAllString(currentPath, rp.replacement)
|
||||
|
||||
|
@@ -44,6 +44,28 @@ func TestReplacePathRegex(t *testing.T) {
|
||||
expectedRawPath: "/who-am-i/and/who-am-i",
|
||||
expectedHeader: "/whoami/and/whoami",
|
||||
},
|
||||
{
|
||||
desc: "empty replacement",
|
||||
path: "/whoami/and/whoami",
|
||||
config: dynamic.ReplacePathRegex{
|
||||
Replacement: "",
|
||||
Regex: `/whoami`,
|
||||
},
|
||||
expectedPath: "/and",
|
||||
expectedRawPath: "/and",
|
||||
expectedHeader: "/whoami/and/whoami",
|
||||
},
|
||||
{
|
||||
desc: "empty trimmed replacement",
|
||||
path: "/whoami/and/whoami",
|
||||
config: dynamic.ReplacePathRegex{
|
||||
Replacement: " ",
|
||||
Regex: `/whoami`,
|
||||
},
|
||||
expectedPath: "/and",
|
||||
expectedRawPath: "/and",
|
||||
expectedHeader: "/whoami/and/whoami",
|
||||
},
|
||||
{
|
||||
desc: "no match",
|
||||
path: "/whoami/and/whoami",
|
||||
|
@@ -35,7 +35,6 @@ func TestCNAMEFlatten(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -38,7 +38,6 @@ func TestRequestHost(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -80,7 +79,6 @@ func TestRequestFlattening(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -173,7 +171,6 @@ func Test_parseHost(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -101,7 +101,6 @@ func TestRetry(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -272,7 +271,6 @@ func TestRetryWebsocket(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -37,7 +37,6 @@ func TestSNICheck_ServeHTTP(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -134,7 +134,6 @@ func TestStripPrefix(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -108,7 +108,6 @@ func TestStripPrefixRegex(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.path, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
@@ -39,7 +39,6 @@ func TestNewIPAllowLister(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -81,7 +80,6 @@ func TestIPAllowLister_ServeHTTP(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user