Merge remote-tracking branch 'upstream/v2.2' into mrg-current-v2.2
This commit is contained in:
commit
7affeae480
12 changed files with 136 additions and 55 deletions
|
@ -282,7 +282,7 @@ For example, `CF_API_EMAIL_FILE=/run/secrets/traefik_cf-api-email` could be used
|
|||
|-------------------------------------------------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------|
|
||||
| [ACME DNS](https://github.com/joohoi/acme-dns) | `acme-dns` | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/acme-dns) |
|
||||
| [Alibaba Cloud](https://www.alibabacloud.com) | `alidns` | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/alidns) |
|
||||
| [Auroradns](https://www.pcextreme.com/aurora/dns) | `auroradns` | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT` | [Additional configuration](https://go-acme.github.io/lego/dns/auroradns) |
|
||||
| [Auroradns](https://www.pcextreme.com/dns-health-checks) | `auroradns` | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT` | [Additional configuration](https://go-acme.github.io/lego/dns/auroradns) |
|
||||
| [Autodns](https://www.internetx.com/domains/autodns/) | `autodns` | `AUTODNS_API_USER`, `AUTODNS_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/autodns) |
|
||||
| [Azure](https://azure.microsoft.com/services/dns/) | `azure` | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_METADATA_ENDPOINT]` | [Additional configuration](https://go-acme.github.io/lego/dns/azure) |
|
||||
| [Bindman](https://github.com/labbsr0x/bindman-dns-webhook) | `bindman` | `BINDMAN_MANAGER_ADDRESS` | [Additional configuration](https://go-acme.github.io/lego/dns/bindman) |
|
||||
|
|
|
@ -311,7 +311,7 @@ This value can contains a list of allowed origins.
|
|||
More information including how to use the settings can be found on:
|
||||
|
||||
- [Mozilla.org](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin)
|
||||
- [w3](https://www.w3.org/TR/cors/#access-control-allow-origin-response-header)
|
||||
- [w3](https://fetch.spec.whatwg.org/#http-access-control-allow-origin)
|
||||
- [IETF](https://tools.ietf.org/html/rfc6454#section-7.1)
|
||||
|
||||
Traefik no longer supports the null value, as it is [no longer recommended as a return value](https://w3c.github.io/webappsec-cors-for-developers/#avoid-returning-access-control-allow-origin-null).
|
||||
|
|
|
@ -97,7 +97,7 @@ Then any router can refer to an instance of the wanted middleware.
|
|||
|
||||
```yaml tab="Docker"
|
||||
labels:
|
||||
- "traefik.http.routers.router0.rule=Host(`example.com`) && PathPrefix(`/test`)"
|
||||
- "traefik.http.routers.router0.rule=Host(`test.localhost`) && PathPrefix(`/test`)"
|
||||
- "traefik.http.routers.router0.middlewares=auth"
|
||||
- "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
|
||||
```
|
||||
|
|
|
@ -111,9 +111,9 @@ accessLog:
|
|||
--accesslog.filters.minduration=10ms
|
||||
```
|
||||
|
||||
### Limiting the Fields
|
||||
### Limiting the Fields/Including Headers
|
||||
|
||||
You can decide to limit the logged fields/headers to a given list with the `fields.names` and `fields.header` options
|
||||
You can decide to limit the logged fields/headers to a given list with the `fields.names` and `fields.headers` options.
|
||||
|
||||
Each field can be set to:
|
||||
|
||||
|
@ -121,7 +121,7 @@ Each field can be set to:
|
|||
- `drop` to drop the value
|
||||
- `redact` to replace the value with "redacted"
|
||||
|
||||
The `defaultMode` for `fields.header` is `drop`.
|
||||
The `defaultMode` for `fields.headers` is `drop`.
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
# Limiting the Logs to Specific Fields
|
||||
|
|
|
@ -154,7 +154,7 @@ You can specify which Docker API Endpoint to use with the directive [`endpoint`]
|
|||
|
||||
- Authentication with Client Certificates as described in ["Protect the Docker daemon socket."](https://docs.docker.com/engine/security/https/)
|
||||
- Authorize and filter requests to restrict possible actions with [the TecnativaDocker Socket Proxy](https://github.com/Tecnativa/docker-socket-proxy).
|
||||
- Authorization with the [Docker Authorization Plugin Mechanism](https://docs.docker.com/engine/extend/plugins_authorization/)
|
||||
- Authorization with the [Docker Authorization Plugin Mechanism](https://web.archive.org/web/20190920092526/https://docs.docker.com/engine/extend/plugins_authorization/)
|
||||
- Accounting at networking level, by exposing the socket only inside a Docker private network, only available for Traefik.
|
||||
- Accounting at container level, by exposing the socket on a another container than Traefik's.
|
||||
With Swarm mode, it allows scheduling of Traefik on worker nodes, with only the "socket exposer" container on the manager nodes.
|
||||
|
|
|
@ -291,7 +291,7 @@ you'd add the label `traefik.http.services.<name-of-your-choice>.loadbalancer.pa
|
|||
See [health check](../services/index.md#health-check) for more information.
|
||||
|
||||
```yaml
|
||||
- "traefik.http.services.myservice.loadbalancer.healthcheck.interval=10"
|
||||
- "traefik.http.services.myservice.loadbalancer.healthcheck.interval=10s"
|
||||
```
|
||||
|
||||
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.path`"
|
||||
|
|
|
@ -202,7 +202,7 @@ which in turn will create the resulting routers, services, handlers, etc.
|
|||
See [middlewares](../routers/index.md#middlewares) and [middlewares overview](../../middlewares/overview.md) for more information.
|
||||
|
||||
```yaml
|
||||
traefik.ingress.kubernetes.io/router.middlewares: auth@file,prefix@kuberntescrd,cb@file
|
||||
traefik.ingress.kubernetes.io/router.middlewares: auth@file,prefix@kubernetescrd,cb@file
|
||||
```
|
||||
|
||||
??? info "`traefik.ingress.kubernetes.io/router.priority`"
|
||||
|
|
|
@ -132,19 +132,19 @@ func (x *XForwarded) rewrite(outreq *http.Request) {
|
|||
|
||||
xfProto := outreq.Header.Get(xForwardedProto)
|
||||
if xfProto == "" {
|
||||
if isWebsocketRequest(outreq) {
|
||||
if outreq.TLS != nil {
|
||||
outreq.Header.Set(xForwardedProto, "wss")
|
||||
} else {
|
||||
outreq.Header.Set(xForwardedProto, "ws")
|
||||
}
|
||||
} else {
|
||||
if outreq.TLS != nil {
|
||||
outreq.Header.Set(xForwardedProto, "https")
|
||||
} else {
|
||||
outreq.Header.Set(xForwardedProto, "http")
|
||||
}
|
||||
}
|
||||
|
||||
if isWebsocketRequest(outreq) {
|
||||
if outreq.Header.Get(xForwardedProto) == "https" || outreq.Header.Get(xForwardedProto) == "wss" {
|
||||
outreq.Header.Set(xForwardedProto, "wss")
|
||||
} else {
|
||||
outreq.Header.Set(xForwardedProto, "ws")
|
||||
}
|
||||
}
|
||||
|
||||
if xfPort := outreq.Header.Get(xForwardedPort); xfPort == "" {
|
||||
|
|
|
@ -345,7 +345,23 @@ func (p Provider) getIPAddress(ctx context.Context, container dockerData) string
|
|||
logger.Warnf("Unable to get IP address for container %s : Failed to inspect container ID %s, error: %s", container.Name, connectedContainer, err)
|
||||
return ""
|
||||
}
|
||||
return p.getIPAddress(ctx, parseContainer(containerInspected))
|
||||
|
||||
// Check connected container for traefik.docker.network, falling back to
|
||||
// the network specified on the current container.
|
||||
containerParsed := parseContainer(containerInspected)
|
||||
extraConf, err := p.getConfiguration(containerParsed)
|
||||
|
||||
if err != nil {
|
||||
logger.Warnf("Unable to get IP address for container %s : failed to get extra configuration for container %s: %s", container.Name, containerInspected.Name, err)
|
||||
return ""
|
||||
}
|
||||
|
||||
if extraConf.Docker.Network == "" {
|
||||
extraConf.Docker.Network = container.ExtraConf.Docker.Network
|
||||
}
|
||||
|
||||
containerParsed.ExtraConf = extraConf
|
||||
return p.getIPAddress(ctx, containerParsed)
|
||||
}
|
||||
|
||||
for _, network := range container.NetworkSettings.Networks {
|
||||
|
|
|
@ -128,9 +128,11 @@ func (l *Listener) Shutdown(graceTimeout time.Duration) error {
|
|||
// we find that session, and otherwise we create a new one.
|
||||
// We then send the data the session's readLoop.
|
||||
func (l *Listener) readLoop() {
|
||||
buf := make([]byte, receiveMTU)
|
||||
|
||||
for {
|
||||
// Allocating a new buffer for every read avoids
|
||||
// overwriting data in c.msgs in case the next packet is received
|
||||
// before c.msgs is emptied via Read()
|
||||
buf := make([]byte, receiveMTU)
|
||||
n, raddr, err := l.pConn.ReadFrom(buf)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -177,7 +179,7 @@ func (l *Listener) newConn(rAddr net.Addr) *Conn {
|
|||
readCh: make(chan []byte),
|
||||
sizeCh: make(chan int),
|
||||
doneCh: make(chan struct{}),
|
||||
ticker: time.NewTicker(timeoutTicker),
|
||||
timeout: timeoutTicker,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,7 +196,7 @@ type Conn struct {
|
|||
muActivity sync.RWMutex
|
||||
lastActivity time.Time // the last time the session saw either read or write activity
|
||||
|
||||
ticker *time.Ticker // for timeouts
|
||||
timeout time.Duration // for timeouts
|
||||
doneOnce sync.Once
|
||||
doneCh chan struct{}
|
||||
}
|
||||
|
@ -204,12 +206,15 @@ type Conn struct {
|
|||
// that is to say it waits on readCh to receive the slice of bytes that the Read operation wants to read onto.
|
||||
// The Read operation receives the signal that the data has been written to the slice of bytes through the sizeCh.
|
||||
func (c *Conn) readLoop() {
|
||||
ticker := time.NewTicker(c.timeout)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
if len(c.msgs) == 0 {
|
||||
select {
|
||||
case msg := <-c.receiveCh:
|
||||
c.msgs = append(c.msgs, msg)
|
||||
case <-c.ticker.C:
|
||||
case <-ticker.C:
|
||||
c.muActivity.RLock()
|
||||
deadline := c.lastActivity.Add(connTimeout)
|
||||
c.muActivity.RUnlock()
|
||||
|
@ -229,7 +234,7 @@ func (c *Conn) readLoop() {
|
|||
c.sizeCh <- n
|
||||
case msg := <-c.receiveCh:
|
||||
c.msgs = append(c.msgs, msg)
|
||||
case <-c.ticker.C:
|
||||
case <-ticker.C:
|
||||
c.muActivity.RLock()
|
||||
deadline := c.lastActivity.Add(connTimeout)
|
||||
c.muActivity.RUnlock()
|
||||
|
@ -281,6 +286,5 @@ func (c *Conn) Close() error {
|
|||
c.listener.mu.Lock()
|
||||
defer c.listener.mu.Unlock()
|
||||
delete(c.listener.conns, c.rAddr.String())
|
||||
c.ticker.Stop()
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -10,6 +10,67 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestConsecutiveWrites(t *testing.T) {
|
||||
addr, err := net.ResolveUDPAddr("udp", ":0")
|
||||
require.NoError(t, err)
|
||||
|
||||
ln, err := Listen("udp", addr)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
err := ln.Close()
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
conn, err := ln.Accept()
|
||||
if err == errClosedListener {
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
go func() {
|
||||
b := make([]byte, 2048)
|
||||
b2 := make([]byte, 2048)
|
||||
var n int
|
||||
var n2 int
|
||||
|
||||
n, err = conn.Read(b)
|
||||
require.NoError(t, err)
|
||||
// Wait to make sure that the second packet is received
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
n2, err = conn.Read(b2)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = conn.Write(b[:n])
|
||||
require.NoError(t, err)
|
||||
_, err = conn.Write(b2[:n2])
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
}
|
||||
}()
|
||||
|
||||
udpConn, err := net.Dial("udp", ln.Addr().String())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Send multiple packets of different content and length consecutively
|
||||
// Read back packets afterwards and make sure that content matches
|
||||
// This checks if any buffers are overwritten while the receiver is enqueuing multiple packets
|
||||
b := make([]byte, 2048)
|
||||
var n int
|
||||
_, err = udpConn.Write([]byte("TESTLONG0"))
|
||||
require.NoError(t, err)
|
||||
_, err = udpConn.Write([]byte("1TEST"))
|
||||
require.NoError(t, err)
|
||||
|
||||
n, err = udpConn.Read(b)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "TESTLONG0", string(b[:n]))
|
||||
n, err = udpConn.Read(b)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "1TEST", string(b[:n]))
|
||||
}
|
||||
|
||||
func TestListenNotBlocking(t *testing.T) {
|
||||
addr, err := net.ResolveUDPAddr("udp", ":0")
|
||||
|
||||
|
|
Loading…
Reference in a new issue