Configurable path for sticky cookies

This commit is contained in:
IIpragmaII 2024-11-06 16:04:04 +01:00 committed by GitHub
parent 552bd8f180
commit ec00c4aa42
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 530 additions and 26 deletions

View file

@ -191,6 +191,7 @@
- "traefik.http.services.service02.loadbalancer.sticky.cookie.httponly=true" - "traefik.http.services.service02.loadbalancer.sticky.cookie.httponly=true"
- "traefik.http.services.service02.loadbalancer.sticky.cookie.maxage=42" - "traefik.http.services.service02.loadbalancer.sticky.cookie.maxage=42"
- "traefik.http.services.service02.loadbalancer.sticky.cookie.name=foobar" - "traefik.http.services.service02.loadbalancer.sticky.cookie.name=foobar"
- "traefik.http.services.service02.loadbalancer.sticky.cookie.path=foobar"
- "traefik.http.services.service02.loadbalancer.sticky.cookie.samesite=foobar" - "traefik.http.services.service02.loadbalancer.sticky.cookie.samesite=foobar"
- "traefik.http.services.service02.loadbalancer.sticky.cookie.secure=true" - "traefik.http.services.service02.loadbalancer.sticky.cookie.secure=true"
- "traefik.http.services.service02.loadbalancer.server.port=foobar" - "traefik.http.services.service02.loadbalancer.server.port=foobar"

View file

@ -55,6 +55,7 @@
httpOnly = true httpOnly = true
sameSite = "foobar" sameSite = "foobar"
maxAge = 42 maxAge = 42
path = "foobar"
[[http.services.Service02.loadBalancer.servers]] [[http.services.Service02.loadBalancer.servers]]
url = "foobar" url = "foobar"
@ -112,6 +113,7 @@
httpOnly = true httpOnly = true
sameSite = "foobar" sameSite = "foobar"
maxAge = 42 maxAge = 42
path = "foobar"
[http.services.Service04.weighted.healthCheck] [http.services.Service04.weighted.healthCheck]
[http.middlewares] [http.middlewares]
[http.middlewares.Middleware01] [http.middlewares.Middleware01]

View file

@ -63,6 +63,7 @@ http:
httpOnly: true httpOnly: true
sameSite: foobar sameSite: foobar
maxAge: 42 maxAge: 42
path: foobar
servers: servers:
- url: foobar - url: foobar
weight: 42 weight: 42
@ -113,6 +114,7 @@ http:
httpOnly: true httpOnly: true
sameSite: foobar sameSite: foobar
maxAge: 42 maxAge: 42
path: foobar
healthCheck: {} healthCheck: {}
middlewares: middlewares:
Middleware01: Middleware01:

View file

@ -242,13 +242,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.
@ -1133,13 +1139,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.
@ -2686,13 +2698,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.
@ -2793,13 +2811,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.
@ -2976,13 +3000,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.
@ -3023,13 +3053,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.

View file

@ -266,6 +266,7 @@ THIS FILE MUST NOT BE EDITED BY HAND
| `traefik/http/services/Service02/loadBalancer/sticky/cookie/httpOnly` | `true` | | `traefik/http/services/Service02/loadBalancer/sticky/cookie/httpOnly` | `true` |
| `traefik/http/services/Service02/loadBalancer/sticky/cookie/maxAge` | `42` | | `traefik/http/services/Service02/loadBalancer/sticky/cookie/maxAge` | `42` |
| `traefik/http/services/Service02/loadBalancer/sticky/cookie/name` | `foobar` | | `traefik/http/services/Service02/loadBalancer/sticky/cookie/name` | `foobar` |
| `traefik/http/services/Service02/loadBalancer/sticky/cookie/path` | `foobar` |
| `traefik/http/services/Service02/loadBalancer/sticky/cookie/sameSite` | `foobar` | | `traefik/http/services/Service02/loadBalancer/sticky/cookie/sameSite` | `foobar` |
| `traefik/http/services/Service02/loadBalancer/sticky/cookie/secure` | `true` | | `traefik/http/services/Service02/loadBalancer/sticky/cookie/secure` | `true` |
| `traefik/http/services/Service03/mirroring/healthCheck` | `` | | `traefik/http/services/Service03/mirroring/healthCheck` | `` |
@ -284,6 +285,7 @@ THIS FILE MUST NOT BE EDITED BY HAND
| `traefik/http/services/Service04/weighted/sticky/cookie/httpOnly` | `true` | | `traefik/http/services/Service04/weighted/sticky/cookie/httpOnly` | `true` |
| `traefik/http/services/Service04/weighted/sticky/cookie/maxAge` | `42` | | `traefik/http/services/Service04/weighted/sticky/cookie/maxAge` | `42` |
| `traefik/http/services/Service04/weighted/sticky/cookie/name` | `foobar` | | `traefik/http/services/Service04/weighted/sticky/cookie/name` | `foobar` |
| `traefik/http/services/Service04/weighted/sticky/cookie/path` | `foobar` |
| `traefik/http/services/Service04/weighted/sticky/cookie/sameSite` | `foobar` | | `traefik/http/services/Service04/weighted/sticky/cookie/sameSite` | `foobar` |
| `traefik/http/services/Service04/weighted/sticky/cookie/secure` | `true` | | `traefik/http/services/Service04/weighted/sticky/cookie/secure` | `true` |
| `traefik/tcp/middlewares/TCPMiddleware01/ipAllowList/sourceRange/0` | `foobar` | | `traefik/tcp/middlewares/TCPMiddleware01/ipAllowList/sourceRange/0` | `foobar` |

View file

@ -242,13 +242,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.

View file

@ -409,13 +409,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.

View file

@ -279,13 +279,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.
@ -386,13 +392,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.
@ -569,13 +581,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.
@ -616,13 +634,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.

View file

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

View file

@ -380,6 +380,14 @@ you'd add the label `traefik.http.services.<name-of-your-choice>.loadbalancer.pa
- "traefik.http.services.myservice.loadbalancer.sticky.cookie.name=foobar" - "traefik.http.services.myservice.loadbalancer.sticky.cookie.name=foobar"
``` ```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.path`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.sticky.cookie.path=/foobar"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.secure`" ??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.secure`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information. See [sticky sessions](../services/index.md#sticky-sessions) for more information.

View file

@ -267,6 +267,14 @@ you'd add the label `traefik.http.services.{name-of-your-choice}.loadbalancer.pa
traefik.http.services.myservice.loadbalancer.sticky.cookie.name=foobar traefik.http.services.myservice.loadbalancer.sticky.cookie.name=foobar
``` ```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.path`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```yaml
traefik.http.services.myservice.loadbalancer.sticky.cookie.path=/foobar
```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.secure`" ??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.secure`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information. See [sticky sessions](../services/index.md#sticky-sessions) for more information.

View file

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

View file

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

View file

@ -228,6 +228,14 @@ A Story of key & values
|-------------------------------------------------------------------|----------| |-------------------------------------------------------------------|----------|
| `traefik/http/services/myservice/loadbalancer/sticky/cookie/name` | `foobar` | | `traefik/http/services/myservice/loadbalancer/sticky/cookie/name` | `foobar` |
??? info "`traefik/http/services/<service_name>/loadbalancer/sticky/cookie/path`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
| Key (Path) | Value |
|-------------------------------------------------------------------|-----------|
| `traefik/http/services/myservice/loadbalancer/sticky/cookie/path` | `/foobar` |
??? info "`traefik/http/services/<service_name>/loadbalancer/sticky/cookie/secure`" ??? info "`traefik/http/services/<service_name>/loadbalancer/sticky/cookie/secure`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information. See [sticky sessions](../services/index.md#sticky-sessions) for more information.
@ -320,6 +328,12 @@ A Story of key & values
|----------------------------------------------------------------------|-------| |----------------------------------------------------------------------|-------|
| `traefik/http/services/<service_name>/weighted/sticky/cookie/maxage` | `42` | | `traefik/http/services/<service_name>/weighted/sticky/cookie/maxage` | `42` |
??? info "`traefik/http/services/<service_name>/weighted/sticky/cookie/path`"
| Key (Path) | Value |
|----------------------------------------------------------------------|-----------|
| `traefik/http/services/<service_name>/weighted/sticky/cookie/path` | `/foobar` |
### Middleware ### Middleware
More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md). More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md).

View file

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

View file

@ -394,6 +394,14 @@ you'd add the label `traefik.http.services.<name-of-your-choice>.loadbalancer.pa
- "traefik.http.services.myservice.loadbalancer.sticky.cookie.name=foobar" - "traefik.http.services.myservice.loadbalancer.sticky.cookie.name=foobar"
``` ```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.path`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.sticky.cookie.path=/foobar"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.secure`" ??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.secure`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information. See [sticky sessions](../services/index.md#sticky-sessions) for more information.

View file

@ -242,13 +242,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.
@ -1133,13 +1139,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.
@ -2686,13 +2698,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.
@ -2793,13 +2811,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.
@ -2976,13 +3000,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.
@ -3023,13 +3053,19 @@ spec:
type: boolean type: boolean
maxAge: maxAge:
description: |- description: |-
MaxAge indicates the number of seconds until the cookie expires. MaxAge defines the number of seconds until the cookie expires.
When set to a negative number, the cookie expires immediately. When set to a negative number, the cookie expires immediately.
When set to zero, the cookie never expires. When set to zero, the cookie never expires.
type: integer type: integer
name: name:
description: Name defines the Cookie name. description: Name defines the Cookie name.
type: string type: string
path:
description: |-
Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
When not provided the cookie will be sent on every request to the domain.
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
type: string
sameSite: sameSite:
description: |- description: |-
SameSite defines the same site policy. SameSite defines the same site policy.

View file

@ -175,10 +175,20 @@ type Cookie struct {
// SameSite defines the same site policy. // SameSite defines the same site policy.
// More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite // More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
SameSite string `json:"sameSite,omitempty" toml:"sameSite,omitempty" yaml:"sameSite,omitempty" export:"true"` SameSite string `json:"sameSite,omitempty" toml:"sameSite,omitempty" yaml:"sameSite,omitempty" export:"true"`
// MaxAge indicates the number of seconds until the cookie expires. // MaxAge defines the number of seconds until the cookie expires.
// When set to a negative number, the cookie expires immediately. // When set to a negative number, the cookie expires immediately.
// When set to zero, the cookie never expires. // When set to zero, the cookie never expires.
MaxAge int `json:"maxAge,omitempty" toml:"maxAge,omitempty" yaml:"maxAge,omitempty" export:"true"` MaxAge int `json:"maxAge,omitempty" toml:"maxAge,omitempty" yaml:"maxAge,omitempty" export:"true"`
// Path defines the path that must exist in the requested URL for the browser to send the Cookie header.
// When not provided the cookie will be sent on every request to the domain.
// More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#pathpath-value
Path *string `json:"path,omitempty" toml:"path,omitempty" yaml:"path,omitempty" export:"true"`
}
// SetDefaults set the default values for a Cookie.
func (c *Cookie) SetDefaults() {
defaultPath := "/"
c.Path = &defaultPath
} }
// +k8s:deepcopy-gen=true // +k8s:deepcopy-gen=true

View file

@ -266,6 +266,11 @@ func (in *ContentType) DeepCopy() *ContentType {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Cookie) DeepCopyInto(out *Cookie) { func (in *Cookie) DeepCopyInto(out *Cookie) {
*out = *in *out = *in
if in.Path != nil {
in, out := &in.Path, &out.Path
*out = new(string)
**out = **in
}
return return
} }
@ -1515,7 +1520,7 @@ func (in *Sticky) DeepCopyInto(out *Sticky) {
if in.Cookie != nil { if in.Cookie != nil {
in, out := &in.Cookie, &out.Cookie in, out := &in.Cookie, &out.Cookie
*out = new(Cookie) *out = new(Cookie)
**out = **in (*in).DeepCopyInto(*out)
} }
return return
} }

View file

@ -174,6 +174,7 @@ func TestDecodeConfiguration(t *testing.T) {
"traefik.http.services.Service0.loadbalancer.server.port": "8080", "traefik.http.services.Service0.loadbalancer.server.port": "8080",
"traefik.http.services.Service0.loadbalancer.sticky.cookie.name": "foobar", "traefik.http.services.Service0.loadbalancer.sticky.cookie.name": "foobar",
"traefik.http.services.Service0.loadbalancer.sticky.cookie.secure": "true", "traefik.http.services.Service0.loadbalancer.sticky.cookie.secure": "true",
"traefik.http.services.Service0.loadbalancer.sticky.cookie.path": "/foobar",
"traefik.http.services.Service0.loadbalancer.serversTransport": "foobar", "traefik.http.services.Service0.loadbalancer.serversTransport": "foobar",
"traefik.http.services.Service1.loadbalancer.healthcheck.headers.name0": "foobar", "traefik.http.services.Service1.loadbalancer.healthcheck.headers.name0": "foobar",
"traefik.http.services.Service1.loadbalancer.healthcheck.headers.name1": "foobar", "traefik.http.services.Service1.loadbalancer.healthcheck.headers.name1": "foobar",
@ -674,6 +675,7 @@ func TestDecodeConfiguration(t *testing.T) {
Name: "foobar", Name: "foobar",
Secure: true, Secure: true,
HTTPOnly: false, HTTPOnly: false,
Path: func(v string) *string { return &v }("/foobar"),
}, },
}, },
Servers: []dynamic.Server{ Servers: []dynamic.Server{
@ -1196,6 +1198,7 @@ func TestEncodeConfiguration(t *testing.T) {
Cookie: &dynamic.Cookie{ Cookie: &dynamic.Cookie{
Name: "foobar", Name: "foobar",
HTTPOnly: true, HTTPOnly: true,
Path: func(v string) *string { return &v }("/foobar"),
}, },
}, },
Servers: []dynamic.Server{ Servers: []dynamic.Server{
@ -1433,6 +1436,7 @@ func TestEncodeConfiguration(t *testing.T) {
"traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.HTTPOnly": "true", "traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.HTTPOnly": "true",
"traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.Secure": "false", "traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.Secure": "false",
"traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.MaxAge": "0", "traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.MaxAge": "0",
"traefik.HTTP.Services.Service0.LoadBalancer.Sticky.Cookie.Path": "/foobar",
"traefik.HTTP.Services.Service0.LoadBalancer.ServersTransport": "foobar", "traefik.HTTP.Services.Service0.LoadBalancer.ServersTransport": "foobar",
"traefik.HTTP.Services.Service1.LoadBalancer.HealthCheck.Headers.name0": "foobar", "traefik.HTTP.Services.Service1.LoadBalancer.HealthCheck.Headers.name0": "foobar",
"traefik.HTTP.Services.Service1.LoadBalancer.HealthCheck.Headers.name1": "foobar", "traefik.HTTP.Services.Service1.LoadBalancer.HealthCheck.Headers.name1": "foobar",

View file

@ -0,0 +1,81 @@
---
apiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: sticky-default
namespace: default
spec:
weighted:
sticky:
cookie:
httpOnly: true
name: cookie
secure: true
sameSite: none
maxAge: 42
services:
- name: whoami3
port: 8443
---
apiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: sticky
namespace: default
spec:
weighted:
sticky:
cookie:
httpOnly: true
name: cookie
secure: true
sameSite: none
maxAge: 42
path: /foo
services:
- name: whoami3
port: 8443
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: test2.route
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`traefik-service`)
kind: Rule
services:
- name: sticky
kind: TraefikService
- name: sticky-default
kind: TraefikService
- match: Host(`k8s-service`)
kind: Rule
services:
- name: whoami
port: 80
sticky:
cookie:
httpOnly: true
name: cookie
secure: true
sameSite: none
maxAge: 42
path: /foo
- name: whoami2
port: 8080
sticky:
cookie:
httpOnly: true
name: cookie
secure: true
sameSite: none
maxAge: 42

View file

@ -248,10 +248,28 @@ func (c configBuilder) buildServicesLB(ctx context.Context, namespace string, tS
}) })
} }
var sticky *dynamic.Sticky
if tService.Weighted.Sticky != nil && tService.Weighted.Sticky.Cookie != nil {
sticky = &dynamic.Sticky{
Cookie: &dynamic.Cookie{
Name: tService.Weighted.Sticky.Cookie.Name,
Secure: tService.Weighted.Sticky.Cookie.Secure,
HTTPOnly: tService.Weighted.Sticky.Cookie.HTTPOnly,
SameSite: tService.Weighted.Sticky.Cookie.SameSite,
MaxAge: tService.Weighted.Sticky.Cookie.MaxAge,
},
}
sticky.Cookie.SetDefaults()
if tService.Weighted.Sticky.Cookie.Path != nil {
sticky.Cookie.Path = tService.Weighted.Sticky.Cookie.Path
}
}
conf[id] = &dynamic.Service{ conf[id] = &dynamic.Service{
Weighted: &dynamic.WeightedRoundRobin{ Weighted: &dynamic.WeightedRoundRobin{
Services: wrrServices, Services: wrrServices,
Sticky: tService.Weighted.Sticky, Sticky: sticky,
}, },
} }
return nil return nil
@ -353,7 +371,22 @@ func (c configBuilder) buildServersLB(namespace string, svc traefikv1alpha1.Load
} }
} }
lb.Sticky = svc.Sticky if svc.Sticky != nil && svc.Sticky.Cookie != nil {
lb.Sticky = &dynamic.Sticky{
Cookie: &dynamic.Cookie{
Name: svc.Sticky.Cookie.Name,
Secure: svc.Sticky.Cookie.Secure,
HTTPOnly: svc.Sticky.Cookie.HTTPOnly,
SameSite: svc.Sticky.Cookie.SameSite,
MaxAge: svc.Sticky.Cookie.MaxAge,
},
}
lb.Sticky.Cookie.SetDefaults()
if svc.Sticky.Cookie.Path != nil {
lb.Sticky.Cookie.Path = svc.Sticky.Cookie.Path
}
}
lb.ServersTransport, err = c.makeServersTransportKey(namespace, svc.ServersTransport) lb.ServersTransport, err = c.makeServersTransportKey(namespace, svc.ServersTransport)
if err != nil { if err != nil {

View file

@ -25,6 +25,7 @@ import (
"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/intstr"
kubefake "k8s.io/client-go/kubernetes/fake" kubefake "k8s.io/client-go/kubernetes/fake"
kscheme "k8s.io/client-go/kubernetes/scheme" kscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/utils/pointer"
) )
var _ provider.Provider = (*Provider)(nil) var _ provider.Provider = (*Provider)(nil)
@ -4903,6 +4904,178 @@ func TestLoadIngressRoutes(t *testing.T) {
TLS: &dynamic.TLSConfiguration{}, TLS: &dynamic.TLSConfiguration{},
}, },
}, },
{
desc: "Simple Ingress Route with sticky",
allowCrossNamespace: true,
paths: []string{"services.yml", "with_sticky.yml"},
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
ServersTransports: map[string]*dynamic.TCPServersTransport{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"default-test2-route-840425136fbd5d85a4ad": {
EntryPoints: []string{"web"},
Service: "default-test2-route-840425136fbd5d85a4ad",
Rule: "Host(`k8s-service`)",
},
"default-test2-route-4f06607bbc69f34a4db5": {
EntryPoints: []string{"web"},
Service: "default-test2-route-4f06607bbc69f34a4db5",
Rule: "Host(`traefik-service`)",
},
},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{
"default-test2-route-840425136fbd5d85a4ad": {
Weighted: &dynamic.WeightedRoundRobin{
Services: []dynamic.WRRService{
{
Name: "default-whoami-80",
Weight: Int(1),
},
{
Name: "default-whoami2-8080",
Weight: Int(1),
},
},
},
},
"default-test2-route-4f06607bbc69f34a4db5": {
Weighted: &dynamic.WeightedRoundRobin{
Services: []dynamic.WRRService{
{
Name: "default-sticky",
Weight: Int(1),
},
{
Name: "default-sticky-default",
Weight: Int(1),
},
},
},
},
"default-sticky": {
Weighted: &dynamic.WeightedRoundRobin{
Sticky: &dynamic.Sticky{
Cookie: &dynamic.Cookie{
Name: "cookie",
Secure: true,
HTTPOnly: true,
SameSite: "none",
MaxAge: 42,
Path: pointer.String("/foo"),
},
},
Services: []dynamic.WRRService{
{
Name: "default-whoami3-8443",
Weight: Int(1),
},
},
},
},
"default-sticky-default": {
Weighted: &dynamic.WeightedRoundRobin{
Sticky: &dynamic.Sticky{
Cookie: &dynamic.Cookie{
Name: "cookie",
Secure: true,
HTTPOnly: true,
SameSite: "none",
MaxAge: 42,
Path: pointer.String("/"),
},
},
Services: []dynamic.WRRService{
{
Name: "default-whoami3-8443",
Weight: Int(1),
},
},
},
},
"default-whoami2-8080": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Sticky: &dynamic.Sticky{
Cookie: &dynamic.Cookie{
Name: "cookie",
Secure: true,
HTTPOnly: true,
SameSite: "none",
MaxAge: 42,
Path: pointer.String("/"),
},
},
Servers: []dynamic.Server{
{
URL: "http://10.10.0.3:8080",
},
{
URL: "http://10.10.0.4:8080",
},
},
PassHostHeader: Bool(true),
ResponseForwarding: &dynamic.ResponseForwarding{
FlushInterval: ptypes.Duration(100 * time.Millisecond),
},
},
},
"default-whoami-80": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Sticky: &dynamic.Sticky{
Cookie: &dynamic.Cookie{
Name: "cookie",
Secure: true,
HTTPOnly: true,
SameSite: "none",
MaxAge: 42,
Path: pointer.String("/foo"),
},
},
Servers: []dynamic.Server{
{
URL: "http://10.10.0.1:80",
},
{
URL: "http://10.10.0.2:80",
},
},
PassHostHeader: Bool(true),
ResponseForwarding: &dynamic.ResponseForwarding{
FlushInterval: ptypes.Duration(100 * time.Millisecond),
},
},
},
"default-whoami3-8443": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://10.10.0.7:8443",
},
{
URL: "http://10.10.0.8:8443",
},
},
PassHostHeader: Bool(true),
ResponseForwarding: &dynamic.ResponseForwarding{
FlushInterval: ptypes.Duration(100 * time.Millisecond),
},
},
},
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{},
},
},
} }
for _, test := range testCases { for _, test := range testCases {

View file

@ -113,6 +113,7 @@ func Test_parseServiceConfig(t *testing.T) {
"traefik.ingress.kubernetes.io/service.sticky.cookie.name": "foobar", "traefik.ingress.kubernetes.io/service.sticky.cookie.name": "foobar",
"traefik.ingress.kubernetes.io/service.sticky.cookie.secure": "true", "traefik.ingress.kubernetes.io/service.sticky.cookie.secure": "true",
"traefik.ingress.kubernetes.io/service.sticky.cookie.samesite": "none", "traefik.ingress.kubernetes.io/service.sticky.cookie.samesite": "none",
"traefik.ingress.kubernetes.io/service.sticky.cookie.path": "foobar",
}, },
expected: &ServiceConfig{ expected: &ServiceConfig{
Service: &ServiceIng{ Service: &ServiceIng{
@ -122,6 +123,7 @@ func Test_parseServiceConfig(t *testing.T) {
Secure: true, Secure: true,
HTTPOnly: true, HTTPOnly: true,
SameSite: "none", SameSite: "none",
Path: String("foobar"),
}, },
}, },
ServersScheme: "protocol", ServersScheme: "protocol",
@ -138,7 +140,11 @@ func Test_parseServiceConfig(t *testing.T) {
}, },
expected: &ServiceConfig{ expected: &ServiceConfig{
Service: &ServiceIng{ Service: &ServiceIng{
Sticky: &dynamic.Sticky{Cookie: &dynamic.Cookie{}}, Sticky: &dynamic.Sticky{
Cookie: &dynamic.Cookie{
Path: String("/"),
},
},
PassHostHeader: Bool(true), PassHostHeader: Bool(true),
}, },
}, },

View file

@ -24,6 +24,8 @@ var _ provider.Provider = (*Provider)(nil)
func Bool(v bool) *bool { return &v } func Bool(v bool) *bool { return &v }
func String(v string) *string { return &v }
func TestLoadConfigurationFromIngresses(t *testing.T) { func TestLoadConfigurationFromIngresses(t *testing.T) {
testCases := []struct { testCases := []struct {
desc string desc string
@ -126,6 +128,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
Name: "foobar", Name: "foobar",
Secure: true, Secure: true,
HTTPOnly: true, HTTPOnly: true,
Path: String("/"),
}, },
}, },
Servers: []dynamic.Server{ Servers: []dynamic.Server{

View file

@ -58,6 +58,7 @@ func Test_buildConfiguration(t *testing.T) {
"traefik/http/services/Service01/loadBalancer/sticky/cookie/name": "foobar", "traefik/http/services/Service01/loadBalancer/sticky/cookie/name": "foobar",
"traefik/http/services/Service01/loadBalancer/sticky/cookie/secure": "true", "traefik/http/services/Service01/loadBalancer/sticky/cookie/secure": "true",
"traefik/http/services/Service01/loadBalancer/sticky/cookie/httpOnly": "true", "traefik/http/services/Service01/loadBalancer/sticky/cookie/httpOnly": "true",
"traefik/http/services/Service01/loadBalancer/sticky/cookie/path": "foobar",
"traefik/http/services/Service01/loadBalancer/servers/0/url": "foobar", "traefik/http/services/Service01/loadBalancer/servers/0/url": "foobar",
"traefik/http/services/Service01/loadBalancer/servers/1/url": "foobar", "traefik/http/services/Service01/loadBalancer/servers/1/url": "foobar",
"traefik/http/services/Service02/mirroring/service": "foobar", "traefik/http/services/Service02/mirroring/service": "foobar",
@ -70,6 +71,7 @@ func Test_buildConfiguration(t *testing.T) {
"traefik/http/services/Service03/weighted/sticky/cookie/name": "foobar", "traefik/http/services/Service03/weighted/sticky/cookie/name": "foobar",
"traefik/http/services/Service03/weighted/sticky/cookie/secure": "true", "traefik/http/services/Service03/weighted/sticky/cookie/secure": "true",
"traefik/http/services/Service03/weighted/sticky/cookie/httpOnly": "true", "traefik/http/services/Service03/weighted/sticky/cookie/httpOnly": "true",
"traefik/http/services/Service03/weighted/sticky/cookie/path": "foobar",
"traefik/http/services/Service03/weighted/services/0/name": "foobar", "traefik/http/services/Service03/weighted/services/0/name": "foobar",
"traefik/http/services/Service03/weighted/services/0/weight": "42", "traefik/http/services/Service03/weighted/services/0/weight": "42",
"traefik/http/services/Service03/weighted/services/1/name": "foobar", "traefik/http/services/Service03/weighted/services/1/name": "foobar",
@ -642,6 +644,7 @@ func Test_buildConfiguration(t *testing.T) {
Name: "foobar", Name: "foobar",
Secure: true, Secure: true,
HTTPOnly: true, HTTPOnly: true,
Path: func(v string) *string { return &v }("foobar"),
}, },
}, },
Servers: []dynamic.Server{ Servers: []dynamic.Server{
@ -708,6 +711,7 @@ func Test_buildConfiguration(t *testing.T) {
Name: "foobar", Name: "foobar",
Secure: true, Secure: true,
HTTPOnly: true, HTTPOnly: true,
Path: func(v string) *string { return &v }("foobar"),
}, },
}, },
}, },

View file

@ -26,6 +26,7 @@ type stickyCookie struct {
httpOnly bool httpOnly bool
sameSite string sameSite string
maxAge int maxAge int
path string
} }
func convertSameSite(sameSite string) http.SameSite { func convertSameSite(sameSite string) http.SameSite {
@ -79,6 +80,10 @@ func New(sticky *dynamic.Sticky, wantHealthCheck bool) *Balancer {
httpOnly: sticky.Cookie.HTTPOnly, httpOnly: sticky.Cookie.HTTPOnly,
sameSite: sticky.Cookie.SameSite, sameSite: sticky.Cookie.SameSite,
maxAge: sticky.Cookie.MaxAge, maxAge: sticky.Cookie.MaxAge,
path: "/",
}
if sticky.Cookie.Path != nil {
balancer.stickyCookie.path = *sticky.Cookie.Path
} }
} }
@ -236,7 +241,7 @@ func (b *Balancer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
cookie := &http.Cookie{ cookie := &http.Cookie{
Name: b.stickyCookie.name, Name: b.stickyCookie.name,
Value: hash(server.name), Value: hash(server.name),
Path: "/", Path: b.stickyCookie.path,
HttpOnly: b.stickyCookie.httpOnly, HttpOnly: b.stickyCookie.httpOnly,
Secure: b.stickyCookie.secure, Secure: b.stickyCookie.secure,
SameSite: convertSameSite(b.stickyCookie.sameSite), SameSite: convertSameSite(b.stickyCookie.sameSite),

View file

@ -226,6 +226,7 @@ func TestSticky(t *testing.T) {
HTTPOnly: true, HTTPOnly: true,
SameSite: "none", SameSite: "none",
MaxAge: 42, MaxAge: 42,
Path: func(v string) *string { return &v }("/foo"),
}, },
}, false) }, false)
@ -263,6 +264,7 @@ func TestSticky(t *testing.T) {
assert.True(t, recorder.cookies["test"].Secure) assert.True(t, recorder.cookies["test"].Secure)
assert.Equal(t, http.SameSiteNoneMode, recorder.cookies["test"].SameSite) assert.Equal(t, http.SameSiteNoneMode, recorder.cookies["test"].SameSite)
assert.Equal(t, 42, recorder.cookies["test"].MaxAge) assert.Equal(t, 42, recorder.cookies["test"].MaxAge)
assert.Equal(t, "/foo", recorder.cookies["test"].Path)
} }
func TestSticky_FallBack(t *testing.T) { func TestSticky_FallBack(t *testing.T) {