fix: stripPrefix middleware with empty resulting path.
This commit is contained in:
parent
cdb2446e32
commit
7afd2dbd20
14 changed files with 426 additions and 245 deletions
|
@ -58,4 +58,5 @@ http:
|
||||||
|
|
||||||
### `prefix`
|
### `prefix`
|
||||||
|
|
||||||
`prefix` is the string to add before the current path in the requested URL. It should include the leading slash (`/`).
|
`prefix` is the string to add before the current path in the requested URL.
|
||||||
|
It should include the leading slash (`/`).
|
||||||
|
|
|
@ -85,3 +85,85 @@ If your backend is serving assets (e.g., images or Javascript files), chances ar
|
||||||
Continuing on the example, the backend should return `/products/shoes/image.png` (and not `/images.png` which Traefik would likely not be able to associate with the same backend).
|
Continuing on the example, the backend should return `/products/shoes/image.png` (and not `/images.png` which Traefik would likely not be able to associate with the same backend).
|
||||||
|
|
||||||
The `X-Forwarded-Prefix` header can be queried to build such URLs dynamically.
|
The `X-Forwarded-Prefix` header can be queried to build such URLs dynamically.
|
||||||
|
|
||||||
|
### `forceSlash`
|
||||||
|
|
||||||
|
_Optional, Default=true_
|
||||||
|
|
||||||
|
```yaml tab="Docker"
|
||||||
|
labels:
|
||||||
|
- "traefik.http.middlewares.example.stripprefix.prefixes=/foobar"
|
||||||
|
- "traefik.http.middlewares.example.stripprefix.forceslash=false"
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Kubernetes"
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: example
|
||||||
|
spec:
|
||||||
|
stripPrefix:
|
||||||
|
prefixes:
|
||||||
|
- "/foobar"
|
||||||
|
forceSlash: false
|
||||||
|
```
|
||||||
|
|
||||||
|
```json tab="Marathon"
|
||||||
|
"labels": {
|
||||||
|
"traefik.http.middlewares.example.stripprefix.prefixes": "/foobar",
|
||||||
|
"traefik.http.middlewares.example.stripprefix.forceslash": "false"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Rancher"
|
||||||
|
labels:
|
||||||
|
- "traefik.http.middlewares.example.stripprefix.prefixes=/foobar"
|
||||||
|
- "traefik.http.middlewares.example.stripprefix.forceSlash=false"
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml tab="File (TOML)"
|
||||||
|
[http.middlewares]
|
||||||
|
[http.middlewares.example.stripPrefix]
|
||||||
|
prefixes = ["/foobar"]
|
||||||
|
forceSlash = false
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="File (YAML)"
|
||||||
|
http:
|
||||||
|
middlewares:
|
||||||
|
example:
|
||||||
|
stripPrefix:
|
||||||
|
prefixes:
|
||||||
|
- "/foobar"
|
||||||
|
forceSlash: false
|
||||||
|
```
|
||||||
|
|
||||||
|
The `forceSlash` option makes sure that the resulting stripped path is not the empty string, by replacing it with `/` when necessary.
|
||||||
|
|
||||||
|
This option was added to keep the initial (non-intuitive) behavior of this middleware, in order to avoid introducing a breaking change.
|
||||||
|
|
||||||
|
It's recommended to explicitly set `forceSlash` to `false`.
|
||||||
|
|
||||||
|
??? info "Behavior examples"
|
||||||
|
|
||||||
|
- `forceSlash=true`
|
||||||
|
|
||||||
|
| Path | Prefix to strip | Result |
|
||||||
|
|------------|-----------------|--------|
|
||||||
|
| `/` | `/` | `/` |
|
||||||
|
| `/foo` | `/foo` | `/` |
|
||||||
|
| `/foo/` | `/foo` | `/` |
|
||||||
|
| `/foo/` | `/foo/` | `/` |
|
||||||
|
| `/bar` | `/foo` | `/bar` |
|
||||||
|
| `/foo/bar` | `/foo` | `/bar` |
|
||||||
|
|
||||||
|
- `forceSlash=false`
|
||||||
|
|
||||||
|
| Path | Prefix to strip | Result |
|
||||||
|
|------------|-----------------|--------|
|
||||||
|
| `/` | `/` | empty |
|
||||||
|
| `/foo` | `/foo` | empty |
|
||||||
|
| `/foo/` | `/foo` | `/` |
|
||||||
|
| `/foo/` | `/foo/` | empty |
|
||||||
|
| `/bar` | `/foo` | `/bar` |
|
||||||
|
| `/foo/bar` | `/foo` | `/bar` |
|
||||||
|
|
|
@ -103,6 +103,7 @@
|
||||||
- "traefik.http.middlewares.middleware17.replacepathregex.regex=foobar"
|
- "traefik.http.middlewares.middleware17.replacepathregex.regex=foobar"
|
||||||
- "traefik.http.middlewares.middleware17.replacepathregex.replacement=foobar"
|
- "traefik.http.middlewares.middleware17.replacepathregex.replacement=foobar"
|
||||||
- "traefik.http.middlewares.middleware18.retry.attempts=42"
|
- "traefik.http.middlewares.middleware18.retry.attempts=42"
|
||||||
|
- "traefik.http.middlewares.middleware19.stripprefix.forceslash=true"
|
||||||
- "traefik.http.middlewares.middleware19.stripprefix.prefixes=foobar, foobar"
|
- "traefik.http.middlewares.middleware19.stripprefix.prefixes=foobar, foobar"
|
||||||
- "traefik.http.middlewares.middleware20.stripprefixregex.regex=foobar, foobar"
|
- "traefik.http.middlewares.middleware20.stripprefixregex.regex=foobar, foobar"
|
||||||
- "traefik.http.routers.router0.entrypoints=foobar, foobar"
|
- "traefik.http.routers.router0.entrypoints=foobar, foobar"
|
||||||
|
@ -129,38 +130,22 @@
|
||||||
- "traefik.http.routers.router1.tls.domains[1].main=foobar"
|
- "traefik.http.routers.router1.tls.domains[1].main=foobar"
|
||||||
- "traefik.http.routers.router1.tls.domains[1].sans=foobar, foobar"
|
- "traefik.http.routers.router1.tls.domains[1].sans=foobar, foobar"
|
||||||
- "traefik.http.routers.router1.tls.options=foobar"
|
- "traefik.http.routers.router1.tls.options=foobar"
|
||||||
- "traefik.http.services.service0.loadbalancer.healthcheck.headers.name0=foobar"
|
- "traefik.http.services.service01.loadbalancer.healthcheck.headers.name0=foobar"
|
||||||
- "traefik.http.services.service0.loadbalancer.healthcheck.headers.name1=foobar"
|
- "traefik.http.services.service01.loadbalancer.healthcheck.headers.name1=foobar"
|
||||||
- "traefik.http.services.service0.loadbalancer.healthcheck.hostname=foobar"
|
- "traefik.http.services.service01.loadbalancer.healthcheck.hostname=foobar"
|
||||||
- "traefik.http.services.service0.loadbalancer.healthcheck.interval=foobar"
|
- "traefik.http.services.service01.loadbalancer.healthcheck.interval=foobar"
|
||||||
- "traefik.http.services.service0.loadbalancer.healthcheck.path=foobar"
|
- "traefik.http.services.service01.loadbalancer.healthcheck.path=foobar"
|
||||||
- "traefik.http.services.service0.loadbalancer.healthcheck.port=42"
|
- "traefik.http.services.service01.loadbalancer.healthcheck.port=42"
|
||||||
- "traefik.http.services.service0.loadbalancer.healthcheck.scheme=foobar"
|
- "traefik.http.services.service01.loadbalancer.healthcheck.scheme=foobar"
|
||||||
- "traefik.http.services.service0.loadbalancer.healthcheck.timeout=foobar"
|
- "traefik.http.services.service01.loadbalancer.healthcheck.timeout=foobar"
|
||||||
- "traefik.http.services.service0.loadbalancer.passhostheader=true"
|
- "traefik.http.services.service01.loadbalancer.passhostheader=true"
|
||||||
- "traefik.http.services.service0.loadbalancer.responseforwarding.flushinterval=foobar"
|
- "traefik.http.services.service01.loadbalancer.responseforwarding.flushinterval=foobar"
|
||||||
- "traefik.http.services.service0.loadbalancer.sticky=true"
|
- "traefik.http.services.service01.loadbalancer.sticky=true"
|
||||||
- "traefik.http.services.service0.loadbalancer.sticky.cookie.httponly=true"
|
- "traefik.http.services.service01.loadbalancer.sticky.cookie.httponly=true"
|
||||||
- "traefik.http.services.service0.loadbalancer.sticky.cookie.name=foobar"
|
- "traefik.http.services.service01.loadbalancer.sticky.cookie.name=foobar"
|
||||||
- "traefik.http.services.service0.loadbalancer.sticky.cookie.secure=true"
|
- "traefik.http.services.service01.loadbalancer.sticky.cookie.secure=true"
|
||||||
- "traefik.http.services.service0.loadbalancer.server.port=foobar"
|
- "traefik.http.services.service01.loadbalancer.server.port=foobar"
|
||||||
- "traefik.http.services.service0.loadbalancer.server.scheme=foobar"
|
- "traefik.http.services.service01.loadbalancer.server.scheme=foobar"
|
||||||
- "traefik.http.services.service1.loadbalancer.healthcheck.headers.name0=foobar"
|
|
||||||
- "traefik.http.services.service1.loadbalancer.healthcheck.headers.name1=foobar"
|
|
||||||
- "traefik.http.services.service1.loadbalancer.healthcheck.hostname=foobar"
|
|
||||||
- "traefik.http.services.service1.loadbalancer.healthcheck.interval=foobar"
|
|
||||||
- "traefik.http.services.service1.loadbalancer.healthcheck.path=foobar"
|
|
||||||
- "traefik.http.services.service1.loadbalancer.healthcheck.port=42"
|
|
||||||
- "traefik.http.services.service1.loadbalancer.healthcheck.scheme=foobar"
|
|
||||||
- "traefik.http.services.service1.loadbalancer.healthcheck.timeout=foobar"
|
|
||||||
- "traefik.http.services.service1.loadbalancer.passhostheader=true"
|
|
||||||
- "traefik.http.services.service1.loadbalancer.responseforwarding.flushinterval=foobar"
|
|
||||||
- "traefik.http.services.service1.loadbalancer.sticky=true"
|
|
||||||
- "traefik.http.services.service1.loadbalancer.sticky.cookie.httponly=true"
|
|
||||||
- "traefik.http.services.service1.loadbalancer.sticky.cookie.name=foobar"
|
|
||||||
- "traefik.http.services.service1.loadbalancer.sticky.cookie.secure=true"
|
|
||||||
- "traefik.http.services.service1.loadbalancer.server.port=foobar"
|
|
||||||
- "traefik.http.services.service1.loadbalancer.server.scheme=foobar"
|
|
||||||
- "traefik.tcp.routers.tcprouter0.entrypoints=foobar, foobar"
|
- "traefik.tcp.routers.tcprouter0.entrypoints=foobar, foobar"
|
||||||
- "traefik.tcp.routers.tcprouter0.rule=foobar"
|
- "traefik.tcp.routers.tcprouter0.rule=foobar"
|
||||||
- "traefik.tcp.routers.tcprouter0.service=foobar"
|
- "traefik.tcp.routers.tcprouter0.service=foobar"
|
||||||
|
@ -183,7 +168,5 @@
|
||||||
- "traefik.tcp.routers.tcprouter1.tls.domains[1].sans=foobar, foobar"
|
- "traefik.tcp.routers.tcprouter1.tls.domains[1].sans=foobar, foobar"
|
||||||
- "traefik.tcp.routers.tcprouter1.tls.options=foobar"
|
- "traefik.tcp.routers.tcprouter1.tls.options=foobar"
|
||||||
- "traefik.tcp.routers.tcprouter1.tls.passthrough=true"
|
- "traefik.tcp.routers.tcprouter1.tls.passthrough=true"
|
||||||
- "traefik.tcp.services.tcpservice0.loadbalancer.server.port=foobar"
|
- "traefik.tcp.services.tcpservice01.loadbalancer.terminationdelay=42"
|
||||||
- "traefik.tcp.services.tcpservice0.loadbalancer.terminationdelay=100"
|
- "traefik.tcp.services.tcpservice01.loadbalancer.server.port=foobar"
|
||||||
- "traefik.tcp.services.tcpservice1.loadbalancer.server.port=foobar"
|
|
||||||
- "traefik.tcp.services.tcpservice1.loadbalancer.terminationdelay=100"
|
|
||||||
|
|
|
@ -245,6 +245,7 @@
|
||||||
[http.middlewares.Middleware19]
|
[http.middlewares.Middleware19]
|
||||||
[http.middlewares.Middleware19.stripPrefix]
|
[http.middlewares.Middleware19.stripPrefix]
|
||||||
prefixes = ["foobar", "foobar"]
|
prefixes = ["foobar", "foobar"]
|
||||||
|
forceSlash = true
|
||||||
[http.middlewares.Middleware20]
|
[http.middlewares.Middleware20]
|
||||||
[http.middlewares.Middleware20.stripPrefixRegex]
|
[http.middlewares.Middleware20.stripPrefixRegex]
|
||||||
regex = ["foobar", "foobar"]
|
regex = ["foobar", "foobar"]
|
||||||
|
@ -284,25 +285,25 @@
|
||||||
main = "foobar"
|
main = "foobar"
|
||||||
sans = ["foobar", "foobar"]
|
sans = ["foobar", "foobar"]
|
||||||
[tcp.services]
|
[tcp.services]
|
||||||
[tcp.services.TCPService0]
|
[tcp.services.TCPService01]
|
||||||
[tcp.services.TCPService0.loadBalancer]
|
[tcp.services.TCPService01.loadBalancer]
|
||||||
terminationDelay = 100
|
terminationDelay = 42
|
||||||
|
|
||||||
[[tcp.services.TCPService0.loadBalancer.servers]]
|
[[tcp.services.TCPService01.loadBalancer.servers]]
|
||||||
address = "foobar"
|
address = "foobar"
|
||||||
|
|
||||||
[[tcp.services.TCPService0.loadBalancer.servers]]
|
[[tcp.services.TCPService01.loadBalancer.servers]]
|
||||||
address = "foobar"
|
address = "foobar"
|
||||||
|
[tcp.services.TCPService02]
|
||||||
|
[tcp.services.TCPService02.weighted]
|
||||||
|
|
||||||
[tcp.services.TCPService1]
|
[[tcp.services.TCPService02.weighted.services]]
|
||||||
[tcp.services.TCPService1.loadBalancer]
|
name = "foobar"
|
||||||
terminationDelay = 100
|
weight = 42
|
||||||
|
|
||||||
[[tcp.services.TCPService1.loadBalancer.servers]]
|
[[tcp.services.TCPService02.weighted.services]]
|
||||||
address = "foobar"
|
name = "foobar"
|
||||||
|
weight = 42
|
||||||
[[tcp.services.TCPService1.loadBalancer.servers]]
|
|
||||||
address = "foobar"
|
|
||||||
|
|
||||||
[tls]
|
[tls]
|
||||||
|
|
||||||
|
|
|
@ -276,6 +276,7 @@ http:
|
||||||
prefixes:
|
prefixes:
|
||||||
- foobar
|
- foobar
|
||||||
- foobar
|
- foobar
|
||||||
|
forceSlash: true
|
||||||
Middleware20:
|
Middleware20:
|
||||||
stripPrefixRegex:
|
stripPrefixRegex:
|
||||||
regex:
|
regex:
|
||||||
|
@ -322,18 +323,19 @@ tcp:
|
||||||
- foobar
|
- foobar
|
||||||
- foobar
|
- foobar
|
||||||
services:
|
services:
|
||||||
TCPService0:
|
TCPService01:
|
||||||
loadBalancer:
|
loadBalancer:
|
||||||
terminationDelay: 100
|
terminationDelay: 42
|
||||||
servers:
|
|
||||||
- address: foobar
|
|
||||||
- address: foobar
|
|
||||||
TCPService1:
|
|
||||||
loadBalancer:
|
|
||||||
terminationDelay: 100
|
|
||||||
servers:
|
servers:
|
||||||
- address: foobar
|
- address: foobar
|
||||||
- address: foobar
|
- address: foobar
|
||||||
|
TCPService02:
|
||||||
|
weighted:
|
||||||
|
services:
|
||||||
|
- name: foobar
|
||||||
|
weight: 42
|
||||||
|
- name: foobar
|
||||||
|
weight: 42
|
||||||
tls:
|
tls:
|
||||||
certificates:
|
certificates:
|
||||||
- certFile: foobar
|
- certFile: foobar
|
||||||
|
|
|
@ -103,6 +103,7 @@
|
||||||
"traefik.http.middlewares.middleware17.replacepathregex.regex": "foobar",
|
"traefik.http.middlewares.middleware17.replacepathregex.regex": "foobar",
|
||||||
"traefik.http.middlewares.middleware17.replacepathregex.replacement": "foobar",
|
"traefik.http.middlewares.middleware17.replacepathregex.replacement": "foobar",
|
||||||
"traefik.http.middlewares.middleware18.retry.attempts": "42",
|
"traefik.http.middlewares.middleware18.retry.attempts": "42",
|
||||||
|
"traefik.http.middlewares.middleware19.stripprefix.forceslash": "true",
|
||||||
"traefik.http.middlewares.middleware19.stripprefix.prefixes": "foobar, foobar",
|
"traefik.http.middlewares.middleware19.stripprefix.prefixes": "foobar, foobar",
|
||||||
"traefik.http.middlewares.middleware20.stripprefixregex.regex": "foobar, foobar",
|
"traefik.http.middlewares.middleware20.stripprefixregex.regex": "foobar, foobar",
|
||||||
"traefik.http.routers.router0.entrypoints": "foobar, foobar",
|
"traefik.http.routers.router0.entrypoints": "foobar, foobar",
|
||||||
|
@ -110,7 +111,6 @@
|
||||||
"traefik.http.routers.router0.priority": "42",
|
"traefik.http.routers.router0.priority": "42",
|
||||||
"traefik.http.routers.router0.rule": "foobar",
|
"traefik.http.routers.router0.rule": "foobar",
|
||||||
"traefik.http.routers.router0.service": "foobar",
|
"traefik.http.routers.router0.service": "foobar",
|
||||||
"traefik.http.routers.router0.tls": "true",
|
|
||||||
"traefik.http.routers.router0.tls.certresolver": "foobar",
|
"traefik.http.routers.router0.tls.certresolver": "foobar",
|
||||||
"traefik.http.routers.router0.tls.domains[0].main": "foobar",
|
"traefik.http.routers.router0.tls.domains[0].main": "foobar",
|
||||||
"traefik.http.routers.router0.tls.domains[0].sans": "foobar, foobar",
|
"traefik.http.routers.router0.tls.domains[0].sans": "foobar, foobar",
|
||||||
|
@ -122,49 +122,30 @@
|
||||||
"traefik.http.routers.router1.priority": "42",
|
"traefik.http.routers.router1.priority": "42",
|
||||||
"traefik.http.routers.router1.rule": "foobar",
|
"traefik.http.routers.router1.rule": "foobar",
|
||||||
"traefik.http.routers.router1.service": "foobar",
|
"traefik.http.routers.router1.service": "foobar",
|
||||||
"traefik.http.routers.router1.tls": "true",
|
|
||||||
"traefik.http.routers.router1.tls.certresolver": "foobar",
|
"traefik.http.routers.router1.tls.certresolver": "foobar",
|
||||||
"traefik.http.routers.router1.tls.domains[0].main": "foobar",
|
"traefik.http.routers.router1.tls.domains[0].main": "foobar",
|
||||||
"traefik.http.routers.router1.tls.domains[0].sans": "foobar, foobar",
|
"traefik.http.routers.router1.tls.domains[0].sans": "foobar, foobar",
|
||||||
"traefik.http.routers.router1.tls.domains[1].main": "foobar",
|
"traefik.http.routers.router1.tls.domains[1].main": "foobar",
|
||||||
"traefik.http.routers.router1.tls.domains[1].sans": "foobar, foobar",
|
"traefik.http.routers.router1.tls.domains[1].sans": "foobar, foobar",
|
||||||
"traefik.http.routers.router1.tls.options": "foobar",
|
"traefik.http.routers.router1.tls.options": "foobar",
|
||||||
"traefik.http.services.service0.loadbalancer.healthcheck.headers.name0": "foobar",
|
"traefik.http.services.service01.loadbalancer.healthcheck.headers.name0": "foobar",
|
||||||
"traefik.http.services.service0.loadbalancer.healthcheck.headers.name1": "foobar",
|
"traefik.http.services.service01.loadbalancer.healthcheck.headers.name1": "foobar",
|
||||||
"traefik.http.services.service0.loadbalancer.healthcheck.hostname": "foobar",
|
"traefik.http.services.service01.loadbalancer.healthcheck.hostname": "foobar",
|
||||||
"traefik.http.services.service0.loadbalancer.healthcheck.interval": "foobar",
|
"traefik.http.services.service01.loadbalancer.healthcheck.interval": "foobar",
|
||||||
"traefik.http.services.service0.loadbalancer.healthcheck.path": "foobar",
|
"traefik.http.services.service01.loadbalancer.healthcheck.path": "foobar",
|
||||||
"traefik.http.services.service0.loadbalancer.healthcheck.port": "42",
|
"traefik.http.services.service01.loadbalancer.healthcheck.port": "42",
|
||||||
"traefik.http.services.service0.loadbalancer.healthcheck.scheme": "foobar",
|
"traefik.http.services.service01.loadbalancer.healthcheck.scheme": "foobar",
|
||||||
"traefik.http.services.service0.loadbalancer.healthcheck.timeout": "foobar",
|
"traefik.http.services.service01.loadbalancer.healthcheck.timeout": "foobar",
|
||||||
"traefik.http.services.service0.loadbalancer.passhostheader": "true",
|
"traefik.http.services.service01.loadbalancer.passhostheader": "true",
|
||||||
"traefik.http.services.service0.loadbalancer.responseforwarding.flushinterval": "foobar",
|
"traefik.http.services.service01.loadbalancer.responseforwarding.flushinterval": "foobar",
|
||||||
"traefik.http.services.service0.loadbalancer.sticky": "true",
|
"traefik.http.services.service01.loadbalancer.sticky.cookie.httponly": "true",
|
||||||
"traefik.http.services.service0.loadbalancer.sticky.cookie.httponly": "true",
|
"traefik.http.services.service01.loadbalancer.sticky.cookie.name": "foobar",
|
||||||
"traefik.http.services.service0.loadbalancer.sticky.cookie.name": "foobar",
|
"traefik.http.services.service01.loadbalancer.sticky.cookie.secure": "true",
|
||||||
"traefik.http.services.service0.loadbalancer.sticky.cookie.secure": "true",
|
"traefik.http.services.service01.loadbalancer.server.port": "foobar",
|
||||||
"traefik.http.services.service0.loadbalancer.server.port": "foobar",
|
"traefik.http.services.service01.loadbalancer.server.scheme": "foobar",
|
||||||
"traefik.http.services.service0.loadbalancer.server.scheme": "foobar",
|
|
||||||
"traefik.http.services.service1.loadbalancer.healthcheck.headers.name0": "foobar",
|
|
||||||
"traefik.http.services.service1.loadbalancer.healthcheck.headers.name1": "foobar",
|
|
||||||
"traefik.http.services.service1.loadbalancer.healthcheck.hostname": "foobar",
|
|
||||||
"traefik.http.services.service1.loadbalancer.healthcheck.interval": "foobar",
|
|
||||||
"traefik.http.services.service1.loadbalancer.healthcheck.path": "foobar",
|
|
||||||
"traefik.http.services.service1.loadbalancer.healthcheck.port": "42",
|
|
||||||
"traefik.http.services.service1.loadbalancer.healthcheck.scheme": "foobar",
|
|
||||||
"traefik.http.services.service1.loadbalancer.healthcheck.timeout": "foobar",
|
|
||||||
"traefik.http.services.service1.loadbalancer.passhostheader": "true",
|
|
||||||
"traefik.http.services.service1.loadbalancer.responseforwarding.flushinterval": "foobar",
|
|
||||||
"traefik.http.services.service1.loadbalancer.sticky": "true",
|
|
||||||
"traefik.http.services.service1.loadbalancer.sticky.cookie.httponly": "true",
|
|
||||||
"traefik.http.services.service1.loadbalancer.sticky.cookie.name": "foobar",
|
|
||||||
"traefik.http.services.service1.loadbalancer.sticky.cookie.secure": "true",
|
|
||||||
"traefik.http.services.service1.loadbalancer.server.port": "foobar",
|
|
||||||
"traefik.http.services.service1.loadbalancer.server.scheme": "foobar",
|
|
||||||
"traefik.tcp.routers.tcprouter0.entrypoints": "foobar, foobar",
|
"traefik.tcp.routers.tcprouter0.entrypoints": "foobar, foobar",
|
||||||
"traefik.tcp.routers.tcprouter0.rule": "foobar",
|
"traefik.tcp.routers.tcprouter0.rule": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter0.service": "foobar",
|
"traefik.tcp.routers.tcprouter0.service": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter0.tls": "true",
|
|
||||||
"traefik.tcp.routers.tcprouter0.tls.certresolver": "foobar",
|
"traefik.tcp.routers.tcprouter0.tls.certresolver": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter0.tls.domains[0].main": "foobar",
|
"traefik.tcp.routers.tcprouter0.tls.domains[0].main": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter0.tls.domains[0].sans": "foobar, foobar",
|
"traefik.tcp.routers.tcprouter0.tls.domains[0].sans": "foobar, foobar",
|
||||||
|
@ -175,7 +156,6 @@
|
||||||
"traefik.tcp.routers.tcprouter1.entrypoints": "foobar, foobar",
|
"traefik.tcp.routers.tcprouter1.entrypoints": "foobar, foobar",
|
||||||
"traefik.tcp.routers.tcprouter1.rule": "foobar",
|
"traefik.tcp.routers.tcprouter1.rule": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter1.service": "foobar",
|
"traefik.tcp.routers.tcprouter1.service": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter1.tls": "true",
|
|
||||||
"traefik.tcp.routers.tcprouter1.tls.certresolver": "foobar",
|
"traefik.tcp.routers.tcprouter1.tls.certresolver": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter1.tls.domains[0].main": "foobar",
|
"traefik.tcp.routers.tcprouter1.tls.domains[0].main": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter1.tls.domains[0].sans": "foobar, foobar",
|
"traefik.tcp.routers.tcprouter1.tls.domains[0].sans": "foobar, foobar",
|
||||||
|
@ -183,7 +163,5 @@
|
||||||
"traefik.tcp.routers.tcprouter1.tls.domains[1].sans": "foobar, foobar",
|
"traefik.tcp.routers.tcprouter1.tls.domains[1].sans": "foobar, foobar",
|
||||||
"traefik.tcp.routers.tcprouter1.tls.options": "foobar",
|
"traefik.tcp.routers.tcprouter1.tls.options": "foobar",
|
||||||
"traefik.tcp.routers.tcprouter1.tls.passthrough": "true",
|
"traefik.tcp.routers.tcprouter1.tls.passthrough": "true",
|
||||||
"traefik.tcp.services.tcpservice0.loadbalancer.server.port": "foobar",
|
"traefik.tcp.services.tcpservice01.loadbalancer.terminationdelay": "42",
|
||||||
"traefik.tcp.services.tcpservice0.loadbalancer.terminationDelay": "100",
|
"traefik.tcp.services.tcpservice01.loadbalancer.server.port": "foobar",
|
||||||
"traefik.tcp.services.tcpservice1.loadbalancer.server.port": "foobar"
|
|
||||||
"traefik.tcp.services.tcpservice1.loadbalancer.terminationDelay": "100",
|
|
||||||
|
|
|
@ -356,6 +356,12 @@ type Retry struct {
|
||||||
// StripPrefix holds the StripPrefix configuration.
|
// StripPrefix holds the StripPrefix configuration.
|
||||||
type StripPrefix struct {
|
type StripPrefix struct {
|
||||||
Prefixes []string `json:"prefixes,omitempty" toml:"prefixes,omitempty" yaml:"prefixes,omitempty"`
|
Prefixes []string `json:"prefixes,omitempty" toml:"prefixes,omitempty" yaml:"prefixes,omitempty"`
|
||||||
|
ForceSlash bool `json:"forceSlash,omitempty" toml:"forceSlash,omitempty" yaml:"forceSlash,omitempty"` // Deprecated
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDefaults Default values for a StripPrefix.
|
||||||
|
func (s *StripPrefix) SetDefaults() {
|
||||||
|
s.ForceSlash = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
|
@ -368,6 +368,7 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"fiibar",
|
"fiibar",
|
||||||
},
|
},
|
||||||
|
ForceSlash: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Middleware18": {
|
"Middleware18": {
|
||||||
|
@ -771,6 +772,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"fiibar",
|
"fiibar",
|
||||||
},
|
},
|
||||||
|
ForceSlash: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Middleware18": {
|
"Middleware18": {
|
||||||
|
@ -1091,6 +1093,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"traefik.HTTP.Middlewares.Middleware15.ReplacePathRegex.Replacement": "foobar",
|
"traefik.HTTP.Middlewares.Middleware15.ReplacePathRegex.Replacement": "foobar",
|
||||||
"traefik.HTTP.Middlewares.Middleware16.Retry.Attempts": "42",
|
"traefik.HTTP.Middlewares.Middleware16.Retry.Attempts": "42",
|
||||||
"traefik.HTTP.Middlewares.Middleware17.StripPrefix.Prefixes": "foobar, fiibar",
|
"traefik.HTTP.Middlewares.Middleware17.StripPrefix.Prefixes": "foobar, fiibar",
|
||||||
|
"traefik.HTTP.Middlewares.Middleware17.StripPrefix.ForceSlash": "true",
|
||||||
"traefik.HTTP.Middlewares.Middleware18.StripPrefixRegex.Regex": "foobar, fiibar",
|
"traefik.HTTP.Middlewares.Middleware18.StripPrefixRegex.Regex": "foobar, fiibar",
|
||||||
"traefik.HTTP.Middlewares.Middleware19.Compress": "true",
|
"traefik.HTTP.Middlewares.Middleware19.Compress": "true",
|
||||||
|
|
||||||
|
|
|
@ -41,23 +41,35 @@ func New(ctx context.Context, next http.Handler, config dynamic.AddPrefix, name
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ap *addPrefix) GetTracingInformation() (string, ext.SpanKindEnum) {
|
func (a *addPrefix) GetTracingInformation() (string, ext.SpanKindEnum) {
|
||||||
return ap.name, tracing.SpanKindNoneEnum
|
return a.name, tracing.SpanKindNoneEnum
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ap *addPrefix) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (a *addPrefix) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
logger := log.FromContext(middlewares.GetLoggerCtx(req.Context(), ap.name, typeName))
|
logger := log.FromContext(middlewares.GetLoggerCtx(req.Context(), a.name, typeName))
|
||||||
|
|
||||||
oldURLPath := req.URL.Path
|
oldURLPath := req.URL.Path
|
||||||
req.URL.Path = ap.prefix + req.URL.Path
|
req.URL.Path = ensureLeadingSlash(a.prefix + req.URL.Path)
|
||||||
logger.Debugf("URL.Path is now %s (was %s).", req.URL.Path, oldURLPath)
|
logger.Debugf("URL.Path is now %s (was %s).", req.URL.Path, oldURLPath)
|
||||||
|
|
||||||
if req.URL.RawPath != "" {
|
if req.URL.RawPath != "" {
|
||||||
oldURLRawPath := req.URL.RawPath
|
oldURLRawPath := req.URL.RawPath
|
||||||
req.URL.RawPath = ap.prefix + req.URL.RawPath
|
req.URL.RawPath = ensureLeadingSlash(a.prefix + req.URL.RawPath)
|
||||||
logger.Debugf("URL.RawPath is now %s (was %s).", req.URL.RawPath, oldURLRawPath)
|
logger.Debugf("URL.RawPath is now %s (was %s).", req.URL.RawPath, oldURLRawPath)
|
||||||
}
|
}
|
||||||
req.RequestURI = req.URL.RequestURI()
|
req.RequestURI = req.URL.RequestURI()
|
||||||
|
|
||||||
ap.next.ServeHTTP(rw, req)
|
a.next.ServeHTTP(rw, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ensureLeadingSlash(str string) string {
|
||||||
|
if str == "" {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
if str[0] == '/' {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
return "/" + str
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
"github.com/containous/traefik/v2/pkg/testhelpers"
|
"github.com/containous/traefik/v2/pkg/testhelpers"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -47,7 +46,6 @@ func TestNewAddPrefix(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddPrefix(t *testing.T) {
|
func TestAddPrefix(t *testing.T) {
|
||||||
logrus.SetLevel(logrus.DebugLevel)
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
prefix dynamic.AddPrefix
|
prefix dynamic.AddPrefix
|
||||||
|
@ -61,6 +59,12 @@ func TestAddPrefix(t *testing.T) {
|
||||||
path: "/b",
|
path: "/b",
|
||||||
expectedPath: "/a/b",
|
expectedPath: "/a/b",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "Works with missing leading slash",
|
||||||
|
prefix: dynamic.AddPrefix{Prefix: "a"},
|
||||||
|
path: "/",
|
||||||
|
expectedPath: "/a/",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "Works with a raw path",
|
desc: "Works with a raw path",
|
||||||
prefix: dynamic.AddPrefix{Prefix: "/a"},
|
prefix: dynamic.AddPrefix{Prefix: "/a"},
|
||||||
|
|
|
@ -22,6 +22,7 @@ const (
|
||||||
type stripPrefix struct {
|
type stripPrefix struct {
|
||||||
next http.Handler
|
next http.Handler
|
||||||
prefixes []string
|
prefixes []string
|
||||||
|
forceSlash bool // TODO Must be removed (breaking), the default behavior must be forceSlash=false
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +31,7 @@ func New(ctx context.Context, next http.Handler, config dynamic.StripPrefix, nam
|
||||||
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
||||||
return &stripPrefix{
|
return &stripPrefix{
|
||||||
prefixes: config.Prefixes,
|
prefixes: config.Prefixes,
|
||||||
|
forceSlash: config.ForceSlash,
|
||||||
next: next,
|
next: next,
|
||||||
name: name,
|
name: name,
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -42,9 +44,9 @@ func (s *stripPrefix) GetTracingInformation() (string, ext.SpanKindEnum) {
|
||||||
func (s *stripPrefix) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (s *stripPrefix) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
for _, prefix := range s.prefixes {
|
for _, prefix := range s.prefixes {
|
||||||
if strings.HasPrefix(req.URL.Path, prefix) {
|
if strings.HasPrefix(req.URL.Path, prefix) {
|
||||||
req.URL.Path = getPrefixStripped(req.URL.Path, prefix)
|
req.URL.Path = s.getPrefixStripped(req.URL.Path, prefix)
|
||||||
if req.URL.RawPath != "" {
|
if req.URL.RawPath != "" {
|
||||||
req.URL.RawPath = getPrefixStripped(req.URL.RawPath, prefix)
|
req.URL.RawPath = s.getPrefixStripped(req.URL.RawPath, prefix)
|
||||||
}
|
}
|
||||||
s.serveRequest(rw, req, strings.TrimSpace(prefix))
|
s.serveRequest(rw, req, strings.TrimSpace(prefix))
|
||||||
return
|
return
|
||||||
|
@ -59,10 +61,25 @@ func (s *stripPrefix) serveRequest(rw http.ResponseWriter, req *http.Request, pr
|
||||||
s.next.ServeHTTP(rw, req)
|
s.next.ServeHTTP(rw, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPrefixStripped(s, prefix string) string {
|
func (s *stripPrefix) getPrefixStripped(urlPath, prefix string) string {
|
||||||
return ensureLeadingSlash(strings.TrimPrefix(s, prefix))
|
if s.forceSlash {
|
||||||
|
// Only for compatibility reason with the previous behavior,
|
||||||
|
// but the previous behavior is wrong.
|
||||||
|
// This needs to be removed in the next breaking version.
|
||||||
|
return "/" + strings.TrimPrefix(strings.TrimPrefix(urlPath, prefix), "/")
|
||||||
|
}
|
||||||
|
|
||||||
|
return ensureLeadingSlash(strings.TrimPrefix(urlPath, prefix))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureLeadingSlash(str string) string {
|
func ensureLeadingSlash(str string) string {
|
||||||
return "/" + strings.TrimPrefix(str, "/")
|
if str == "" {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
if str[0] == '/' {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
return "/" + str
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,17 @@ func TestStripPrefix(t *testing.T) {
|
||||||
expectedStatusCode: http.StatusOK,
|
expectedStatusCode: http.StatusOK,
|
||||||
expectedPath: "/noprefixes",
|
expectedPath: "/noprefixes",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "wildcard (.*) requests (ForceSlash)",
|
||||||
|
config: dynamic.StripPrefix{
|
||||||
|
Prefixes: []string{"/"},
|
||||||
|
ForceSlash: true,
|
||||||
|
},
|
||||||
|
path: "/",
|
||||||
|
expectedStatusCode: http.StatusOK,
|
||||||
|
expectedPath: "/",
|
||||||
|
expectedHeader: "/",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "wildcard (.*) requests",
|
desc: "wildcard (.*) requests",
|
||||||
config: dynamic.StripPrefix{
|
config: dynamic.StripPrefix{
|
||||||
|
@ -38,9 +49,20 @@ func TestStripPrefix(t *testing.T) {
|
||||||
},
|
},
|
||||||
path: "/",
|
path: "/",
|
||||||
expectedStatusCode: http.StatusOK,
|
expectedStatusCode: http.StatusOK,
|
||||||
expectedPath: "/",
|
expectedPath: "",
|
||||||
expectedHeader: "/",
|
expectedHeader: "/",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "prefix and path matching (ForceSlash)",
|
||||||
|
config: dynamic.StripPrefix{
|
||||||
|
Prefixes: []string{"/stat"},
|
||||||
|
ForceSlash: true,
|
||||||
|
},
|
||||||
|
path: "/stat",
|
||||||
|
expectedStatusCode: http.StatusOK,
|
||||||
|
expectedPath: "/",
|
||||||
|
expectedHeader: "/stat",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "prefix and path matching",
|
desc: "prefix and path matching",
|
||||||
config: dynamic.StripPrefix{
|
config: dynamic.StripPrefix{
|
||||||
|
@ -48,9 +70,20 @@ func TestStripPrefix(t *testing.T) {
|
||||||
},
|
},
|
||||||
path: "/stat",
|
path: "/stat",
|
||||||
expectedStatusCode: http.StatusOK,
|
expectedStatusCode: http.StatusOK,
|
||||||
expectedPath: "/",
|
expectedPath: "",
|
||||||
expectedHeader: "/stat",
|
expectedHeader: "/stat",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "path prefix on exactly matching path (ForceSlash)",
|
||||||
|
config: dynamic.StripPrefix{
|
||||||
|
Prefixes: []string{"/stat/"},
|
||||||
|
ForceSlash: true,
|
||||||
|
},
|
||||||
|
path: "/stat/",
|
||||||
|
expectedStatusCode: http.StatusOK,
|
||||||
|
expectedPath: "/",
|
||||||
|
expectedHeader: "/stat/",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "path prefix on exactly matching path",
|
desc: "path prefix on exactly matching path",
|
||||||
config: dynamic.StripPrefix{
|
config: dynamic.StripPrefix{
|
||||||
|
@ -58,7 +91,7 @@ func TestStripPrefix(t *testing.T) {
|
||||||
},
|
},
|
||||||
path: "/stat/",
|
path: "/stat/",
|
||||||
expectedStatusCode: http.StatusOK,
|
expectedStatusCode: http.StatusOK,
|
||||||
expectedPath: "/",
|
expectedPath: "",
|
||||||
expectedHeader: "/stat/",
|
expectedHeader: "/stat/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -101,6 +134,17 @@ func TestStripPrefix(t *testing.T) {
|
||||||
expectedPath: "/us",
|
expectedPath: "/us",
|
||||||
expectedHeader: "/stat",
|
expectedHeader: "/stat",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "later prefix matching (ForceSlash)",
|
||||||
|
config: dynamic.StripPrefix{
|
||||||
|
Prefixes: []string{"/mismatch", "/stat"},
|
||||||
|
ForceSlash: true,
|
||||||
|
},
|
||||||
|
path: "/stat",
|
||||||
|
expectedStatusCode: http.StatusOK,
|
||||||
|
expectedPath: "/",
|
||||||
|
expectedHeader: "/stat",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "later prefix matching",
|
desc: "later prefix matching",
|
||||||
config: dynamic.StripPrefix{
|
config: dynamic.StripPrefix{
|
||||||
|
@ -108,7 +152,7 @@ func TestStripPrefix(t *testing.T) {
|
||||||
},
|
},
|
||||||
path: "/stat",
|
path: "/stat",
|
||||||
expectedStatusCode: http.StatusOK,
|
expectedStatusCode: http.StatusOK,
|
||||||
expectedPath: "/",
|
expectedPath: "",
|
||||||
expectedHeader: "/stat",
|
expectedHeader: "/stat",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -162,12 +206,15 @@ func TestStripPrefix(t *testing.T) {
|
||||||
assert.Equal(t, test.expectedRawPath, actualRawPath, "Unexpected raw path.")
|
assert.Equal(t, test.expectedRawPath, actualRawPath, "Unexpected raw path.")
|
||||||
assert.Equal(t, test.expectedHeader, actualHeader, "Unexpected '%s' header.", ForwardedPrefixHeader)
|
assert.Equal(t, test.expectedHeader, actualHeader, "Unexpected '%s' header.", ForwardedPrefixHeader)
|
||||||
|
|
||||||
expectedURI := test.expectedPath
|
expectedRequestURI := test.expectedPath
|
||||||
if test.expectedRawPath != "" {
|
if test.expectedRawPath != "" {
|
||||||
// go HTTP uses the raw path when existent in the RequestURI
|
// go HTTP uses the raw path when existent in the RequestURI
|
||||||
expectedURI = test.expectedRawPath
|
expectedRequestURI = test.expectedRawPath
|
||||||
}
|
}
|
||||||
assert.Equal(t, expectedURI, requestURI, "Unexpected request URI.")
|
if test.expectedPath == "" {
|
||||||
|
expectedRequestURI = "/"
|
||||||
|
}
|
||||||
|
assert.Equal(t, expectedRequestURI, requestURI, "Unexpected request URI.")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,12 +60,12 @@ func (s *stripPrefixRegex) ServeHTTP(rw http.ResponseWriter, req *http.Request)
|
||||||
|
|
||||||
req.Header.Add(stripprefix.ForwardedPrefixHeader, prefix)
|
req.Header.Add(stripprefix.ForwardedPrefixHeader, prefix)
|
||||||
|
|
||||||
req.URL.Path = strings.Replace(req.URL.Path, prefix, "", 1)
|
req.URL.Path = ensureLeadingSlash(strings.Replace(req.URL.Path, prefix, "", 1))
|
||||||
if req.URL.RawPath != "" {
|
if req.URL.RawPath != "" {
|
||||||
req.URL.RawPath = req.URL.RawPath[len(prefix):]
|
req.URL.RawPath = ensureLeadingSlash(req.URL.RawPath[len(prefix):])
|
||||||
}
|
}
|
||||||
|
|
||||||
req.RequestURI = ensureLeadingSlash(req.URL.RequestURI())
|
req.RequestURI = req.URL.RequestURI()
|
||||||
s.next.ServeHTTP(rw, req)
|
s.next.ServeHTTP(rw, req)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -75,5 +75,13 @@ func (s *stripPrefixRegex) ServeHTTP(rw http.ResponseWriter, req *http.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureLeadingSlash(str string) string {
|
func ensureLeadingSlash(str string) string {
|
||||||
return "/" + strings.TrimPrefix(str, "/")
|
if str == "" {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
if str[0] == '/' {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
return "/" + str
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,42 +31,66 @@ func TestStripPrefixRegex(t *testing.T) {
|
||||||
expectedPath: "/a/test",
|
expectedPath: "/a/test",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/a/test",
|
path: "/a/test/",
|
||||||
expectedStatusCode: http.StatusOK,
|
expectedStatusCode: http.StatusOK,
|
||||||
expectedPath: "/a/test",
|
expectedPath: "/a/test/",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/a/api/",
|
||||||
|
expectedStatusCode: http.StatusOK,
|
||||||
|
expectedPath: "",
|
||||||
|
expectedHeader: "/a/api/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/a/api/test",
|
path: "/a/api/test",
|
||||||
expectedStatusCode: http.StatusOK,
|
expectedStatusCode: http.StatusOK,
|
||||||
expectedPath: "test",
|
expectedPath: "/test",
|
||||||
|
expectedHeader: "/a/api/",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/a/api/test/",
|
||||||
|
expectedStatusCode: http.StatusOK,
|
||||||
|
expectedPath: "/test/",
|
||||||
expectedHeader: "/a/api/",
|
expectedHeader: "/a/api/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/b/api/",
|
path: "/b/api/",
|
||||||
expectedStatusCode: http.StatusOK,
|
expectedStatusCode: http.StatusOK,
|
||||||
|
expectedPath: "",
|
||||||
expectedHeader: "/b/api/",
|
expectedHeader: "/b/api/",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/b/api",
|
||||||
|
expectedStatusCode: http.StatusOK,
|
||||||
|
expectedPath: "/b/api",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/b/api/test1",
|
path: "/b/api/test1",
|
||||||
expectedStatusCode: http.StatusOK,
|
expectedStatusCode: http.StatusOK,
|
||||||
expectedPath: "test1",
|
expectedPath: "/test1",
|
||||||
expectedHeader: "/b/api/",
|
expectedHeader: "/b/api/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/b/api2/test2",
|
path: "/b/api2/test2",
|
||||||
expectedStatusCode: http.StatusOK,
|
expectedStatusCode: http.StatusOK,
|
||||||
expectedPath: "test2",
|
expectedPath: "/test2",
|
||||||
expectedHeader: "/b/api2/",
|
expectedHeader: "/b/api2/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/c/api/123/",
|
path: "/c/api/123/",
|
||||||
expectedStatusCode: http.StatusOK,
|
expectedStatusCode: http.StatusOK,
|
||||||
|
expectedPath: "",
|
||||||
expectedHeader: "/c/api/123/",
|
expectedHeader: "/c/api/123/",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/c/api/123",
|
||||||
|
expectedStatusCode: http.StatusOK,
|
||||||
|
expectedPath: "/c/api/123",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/c/api/123/test3",
|
path: "/c/api/123/test3",
|
||||||
expectedStatusCode: http.StatusOK,
|
expectedStatusCode: http.StatusOK,
|
||||||
expectedPath: "test3",
|
expectedPath: "/test3",
|
||||||
expectedHeader: "/c/api/123/",
|
expectedHeader: "/c/api/123/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -77,8 +101,8 @@ func TestStripPrefixRegex(t *testing.T) {
|
||||||
{
|
{
|
||||||
path: "/a/api/a%2Fb",
|
path: "/a/api/a%2Fb",
|
||||||
expectedStatusCode: http.StatusOK,
|
expectedStatusCode: http.StatusOK,
|
||||||
expectedPath: "a/b",
|
expectedPath: "/a/b",
|
||||||
expectedRawPath: "a%2Fb",
|
expectedRawPath: "/a%2Fb",
|
||||||
expectedHeader: "/a/api/",
|
expectedHeader: "/a/api/",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -88,11 +112,12 @@ func TestStripPrefixRegex(t *testing.T) {
|
||||||
t.Run(test.path, func(t *testing.T) {
|
t.Run(test.path, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
var actualPath, actualRawPath, actualHeader string
|
var actualPath, actualRawPath, actualHeader, requestURI string
|
||||||
handlerPath := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
handlerPath := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
actualPath = r.URL.Path
|
actualPath = r.URL.Path
|
||||||
actualRawPath = r.URL.RawPath
|
actualRawPath = r.URL.RawPath
|
||||||
actualHeader = r.Header.Get(stripprefix.ForwardedPrefixHeader)
|
actualHeader = r.Header.Get(stripprefix.ForwardedPrefixHeader)
|
||||||
|
requestURI = r.RequestURI
|
||||||
})
|
})
|
||||||
handler, err := New(context.Background(), handlerPath, testPrefixRegex, "foo-strip-prefix-regex")
|
handler, err := New(context.Background(), handlerPath, testPrefixRegex, "foo-strip-prefix-regex")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -106,6 +131,18 @@ func TestStripPrefixRegex(t *testing.T) {
|
||||||
assert.Equal(t, test.expectedPath, actualPath, "Unexpected path.")
|
assert.Equal(t, test.expectedPath, actualPath, "Unexpected path.")
|
||||||
assert.Equal(t, test.expectedRawPath, actualRawPath, "Unexpected raw path.")
|
assert.Equal(t, test.expectedRawPath, actualRawPath, "Unexpected raw path.")
|
||||||
assert.Equal(t, test.expectedHeader, actualHeader, "Unexpected '%s' header.", stripprefix.ForwardedPrefixHeader)
|
assert.Equal(t, test.expectedHeader, actualHeader, "Unexpected '%s' header.", stripprefix.ForwardedPrefixHeader)
|
||||||
|
|
||||||
|
if test.expectedPath != test.path {
|
||||||
|
expectedRequestURI := test.expectedPath
|
||||||
|
if test.expectedRawPath != "" {
|
||||||
|
// go HTTP uses the raw path when existent in the RequestURI
|
||||||
|
expectedRequestURI = test.expectedRawPath
|
||||||
|
}
|
||||||
|
if test.expectedPath == "" {
|
||||||
|
expectedRequestURI = "/"
|
||||||
|
}
|
||||||
|
assert.Equal(t, expectedRequestURI, requestURI, "Unexpected request URI.")
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue