feat: add readIdleTimeout and pingTimeout config options to ServersTransport
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
This commit is contained in:
parent
8e32d1913b
commit
1f17731369
14 changed files with 204 additions and 38 deletions
|
@ -52,23 +52,40 @@ spec:
|
||||||
anyOf:
|
anyOf:
|
||||||
- type: integer
|
- type: integer
|
||||||
- type: string
|
- type: string
|
||||||
description: The amount of time to wait until a connection to
|
description: DialTimeout is the amount of time to wait until a
|
||||||
a backend server can be established. If zero, no timeout exists.
|
connection to a backend server can be established. If zero,
|
||||||
|
no timeout exists.
|
||||||
x-kubernetes-int-or-string: true
|
x-kubernetes-int-or-string: true
|
||||||
idleConnTimeout:
|
idleConnTimeout:
|
||||||
anyOf:
|
anyOf:
|
||||||
- type: integer
|
- type: integer
|
||||||
- type: string
|
- type: string
|
||||||
description: The maximum period for which an idle HTTP keep-alive
|
description: IdleConnTimeout is the maximum period for which an
|
||||||
connection will remain open before closing itself.
|
idle HTTP keep-alive connection will remain open before closing
|
||||||
|
itself.
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
pingTimeout:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
description: PingTimeout is the timeout after which the HTTP/2
|
||||||
|
connection will be closed if a response to ping is not received.
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
readIdleTimeout:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
description: ReadIdleTimeout is the timeout after which a health
|
||||||
|
check using ping frame will be carried out if no frame is received
|
||||||
|
on the HTTP/2 connection. If zero, no health check is performed.
|
||||||
x-kubernetes-int-or-string: true
|
x-kubernetes-int-or-string: true
|
||||||
responseHeaderTimeout:
|
responseHeaderTimeout:
|
||||||
anyOf:
|
anyOf:
|
||||||
- type: integer
|
- type: integer
|
||||||
- type: string
|
- type: string
|
||||||
description: The amount of time to wait for a server's response
|
description: ResponseHeaderTimeout is the amount of time to wait
|
||||||
headers after fully writing the request (including its body,
|
for a server's response headers after fully writing the request
|
||||||
if any). If zero, no timeout exists.
|
(including its body, if any). If zero, no timeout exists.
|
||||||
x-kubernetes-int-or-string: true
|
x-kubernetes-int-or-string: true
|
||||||
type: object
|
type: object
|
||||||
insecureSkipVerify:
|
insecureSkipVerify:
|
||||||
|
|
|
@ -324,7 +324,7 @@ serversTransport:
|
||||||
|
|
||||||
`forwardingTimeouts` is about a number of timeouts relevant to when forwarding requests to the backend servers.
|
`forwardingTimeouts` is about a number of timeouts relevant to when forwarding requests to the backend servers.
|
||||||
|
|
||||||
#### forwardingTimeouts.dialTimeout`
|
#### `forwardingTimeouts.dialTimeout`
|
||||||
|
|
||||||
_Optional, Default=30s_
|
_Optional, Default=30s_
|
||||||
|
|
||||||
|
@ -349,7 +349,7 @@ serversTransport:
|
||||||
--serversTransport.forwardingTimeouts.dialTimeout=1s
|
--serversTransport.forwardingTimeouts.dialTimeout=1s
|
||||||
```
|
```
|
||||||
|
|
||||||
#### forwardingTimeouts.responseHeaderTimeout`
|
#### `forwardingTimeouts.responseHeaderTimeout`
|
||||||
|
|
||||||
_Optional, Default=0s_
|
_Optional, Default=0s_
|
||||||
|
|
||||||
|
@ -376,7 +376,7 @@ serversTransport:
|
||||||
--serversTransport.forwardingTimeouts.responseHeaderTimeout=1s
|
--serversTransport.forwardingTimeouts.responseHeaderTimeout=1s
|
||||||
```
|
```
|
||||||
|
|
||||||
#### forwardingTimeouts.idleConnTimeout`
|
#### `forwardingTimeouts.idleConnTimeout`
|
||||||
|
|
||||||
_Optional, Default=90s_
|
_Optional, Default=90s_
|
||||||
|
|
||||||
|
|
|
@ -876,6 +876,78 @@ spec:
|
||||||
idleConnTimeout: "1s"
|
idleConnTimeout: "1s"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
##### `forwardingTimeouts.readIdleTimeout`
|
||||||
|
|
||||||
|
_Optional, Default=0s_
|
||||||
|
|
||||||
|
`readIdleTimeout` is the timeout after which a health check using ping frame will be carried out
|
||||||
|
if no frame is received on the HTTP/2 connection.
|
||||||
|
Note that a ping response will be considered a received frame,
|
||||||
|
so if there is no other traffic on the connection,
|
||||||
|
the health check will be performed every `readIdleTimeout` interval.
|
||||||
|
If zero, no health check is performed.
|
||||||
|
|
||||||
|
```yaml tab="File (YAML)"
|
||||||
|
## Dynamic configuration
|
||||||
|
http:
|
||||||
|
serversTransports:
|
||||||
|
mytransport:
|
||||||
|
forwardingTimeouts:
|
||||||
|
readIdleTimeout: "1s"
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml tab="File (TOML)"
|
||||||
|
## Dynamic configuration
|
||||||
|
[http.serversTransports.mytransport.forwardingTimeouts]
|
||||||
|
readIdleTimeout = "1s"
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Kubernetes"
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: ServersTransport
|
||||||
|
metadata:
|
||||||
|
name: mytransport
|
||||||
|
namespace: default
|
||||||
|
|
||||||
|
spec:
|
||||||
|
forwardingTimeouts:
|
||||||
|
readIdleTimeout: "1s"
|
||||||
|
```
|
||||||
|
|
||||||
|
##### `forwardingTimeouts.pingTimeout`
|
||||||
|
|
||||||
|
_Optional, Default=15s_
|
||||||
|
|
||||||
|
`pingTimeout` is the timeout after which the HTTP/2 connection will be closed
|
||||||
|
if a response to ping is not received.
|
||||||
|
|
||||||
|
```yaml tab="File (YAML)"
|
||||||
|
## Dynamic configuration
|
||||||
|
http:
|
||||||
|
serversTransports:
|
||||||
|
mytransport:
|
||||||
|
forwardingTimeouts:
|
||||||
|
pingTimeout: "1s"
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml tab="File (TOML)"
|
||||||
|
## Dynamic configuration
|
||||||
|
[http.serversTransports.mytransport.forwardingTimeouts]
|
||||||
|
pingTimeout = "1s"
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Kubernetes"
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: ServersTransport
|
||||||
|
metadata:
|
||||||
|
name: mytransport
|
||||||
|
namespace: default
|
||||||
|
|
||||||
|
spec:
|
||||||
|
forwardingTimeouts:
|
||||||
|
pingTimeout: "1s"
|
||||||
|
```
|
||||||
|
|
||||||
### Weighted Round Robin (service)
|
### Weighted Round Robin (service)
|
||||||
|
|
||||||
The WRR is able to load balance the requests between multiple services based on weights.
|
The WRR is able to load balance the requests between multiple services based on weights.
|
||||||
|
|
|
@ -1125,23 +1125,40 @@ spec:
|
||||||
anyOf:
|
anyOf:
|
||||||
- type: integer
|
- type: integer
|
||||||
- type: string
|
- type: string
|
||||||
description: The amount of time to wait until a connection to
|
description: DialTimeout is the amount of time to wait until a
|
||||||
a backend server can be established. If zero, no timeout exists.
|
connection to a backend server can be established. If zero,
|
||||||
|
no timeout exists.
|
||||||
x-kubernetes-int-or-string: true
|
x-kubernetes-int-or-string: true
|
||||||
idleConnTimeout:
|
idleConnTimeout:
|
||||||
anyOf:
|
anyOf:
|
||||||
- type: integer
|
- type: integer
|
||||||
- type: string
|
- type: string
|
||||||
description: The maximum period for which an idle HTTP keep-alive
|
description: IdleConnTimeout is the maximum period for which an
|
||||||
connection will remain open before closing itself.
|
idle HTTP keep-alive connection will remain open before closing
|
||||||
|
itself.
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
pingTimeout:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
description: PingTimeout is the timeout after which the HTTP/2
|
||||||
|
connection will be closed if a response to ping is not received.
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
readIdleTimeout:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
description: ReadIdleTimeout is the timeout after which a health
|
||||||
|
check using ping frame will be carried out if no frame is received
|
||||||
|
on the HTTP/2 connection. If zero, no health check is performed.
|
||||||
x-kubernetes-int-or-string: true
|
x-kubernetes-int-or-string: true
|
||||||
responseHeaderTimeout:
|
responseHeaderTimeout:
|
||||||
anyOf:
|
anyOf:
|
||||||
- type: integer
|
- type: integer
|
||||||
- type: string
|
- type: string
|
||||||
description: The amount of time to wait for a server's response
|
description: ResponseHeaderTimeout is the amount of time to wait
|
||||||
headers after fully writing the request (including its body,
|
for a server's response headers after fully writing the request
|
||||||
if any). If zero, no timeout exists.
|
(including its body, if any). If zero, no timeout exists.
|
||||||
x-kubernetes-int-or-string: true
|
x-kubernetes-int-or-string: true
|
||||||
type: object
|
type: object
|
||||||
insecureSkipVerify:
|
insecureSkipVerify:
|
||||||
|
|
|
@ -147,6 +147,8 @@ func TestDo_dynamicConfiguration(t *testing.T) {
|
||||||
DialTimeout: 42,
|
DialTimeout: 42,
|
||||||
ResponseHeaderTimeout: 42,
|
ResponseHeaderTimeout: 42,
|
||||||
IdleConnTimeout: 42,
|
IdleConnTimeout: 42,
|
||||||
|
ReadIdleTimeout: 42,
|
||||||
|
PingTimeout: 42,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -355,7 +355,9 @@
|
||||||
"forwardingTimeouts": {
|
"forwardingTimeouts": {
|
||||||
"dialTimeout": "42ns",
|
"dialTimeout": "42ns",
|
||||||
"responseHeaderTimeout": "42ns",
|
"responseHeaderTimeout": "42ns",
|
||||||
"idleConnTimeout": "42ns"
|
"idleConnTimeout": "42ns",
|
||||||
|
"readIdleTimeout": "42ns",
|
||||||
|
"pingTimeout": "42ns"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,7 +218,7 @@ type HealthCheck struct{}
|
||||||
|
|
||||||
// ServersTransport options to configure communication between Traefik and the servers.
|
// ServersTransport options to configure communication between Traefik and the servers.
|
||||||
type ServersTransport struct {
|
type ServersTransport struct {
|
||||||
ServerName string `description:"ServerName used to contact the server" json:"serverName,omitempty" toml:"serverName,omitempty" yaml:"serverName,omitempty"`
|
ServerName string `description:"ServerName used to contact the server." json:"serverName,omitempty" toml:"serverName,omitempty" yaml:"serverName,omitempty"`
|
||||||
InsecureSkipVerify bool `description:"Disable SSL certificate verification." json:"insecureSkipVerify,omitempty" toml:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty" export:"true"`
|
InsecureSkipVerify bool `description:"Disable SSL certificate verification." json:"insecureSkipVerify,omitempty" toml:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty" export:"true"`
|
||||||
RootCAs []traefiktls.FileOrContent `description:"Add cert file for self-signed certificate." json:"rootCAs,omitempty" toml:"rootCAs,omitempty" yaml:"rootCAs,omitempty"`
|
RootCAs []traefiktls.FileOrContent `description:"Add cert file for self-signed certificate." json:"rootCAs,omitempty" toml:"rootCAs,omitempty" yaml:"rootCAs,omitempty"`
|
||||||
Certificates traefiktls.Certificates `description:"Certificates for mTLS." json:"certificates,omitempty" toml:"certificates,omitempty" yaml:"certificates,omitempty" export:"true"`
|
Certificates traefiktls.Certificates `description:"Certificates for mTLS." json:"certificates,omitempty" toml:"certificates,omitempty" yaml:"certificates,omitempty" export:"true"`
|
||||||
|
@ -234,11 +234,14 @@ type ServersTransport struct {
|
||||||
type ForwardingTimeouts struct {
|
type ForwardingTimeouts struct {
|
||||||
DialTimeout ptypes.Duration `description:"The amount of time to wait until a connection to a backend server can be established. If zero, no timeout exists." json:"dialTimeout,omitempty" toml:"dialTimeout,omitempty" yaml:"dialTimeout,omitempty" export:"true"`
|
DialTimeout ptypes.Duration `description:"The amount of time to wait until a connection to a backend server can be established. If zero, no timeout exists." json:"dialTimeout,omitempty" toml:"dialTimeout,omitempty" yaml:"dialTimeout,omitempty" export:"true"`
|
||||||
ResponseHeaderTimeout ptypes.Duration `description:"The amount of time to wait for a server's response headers after fully writing the request (including its body, if any). If zero, no timeout exists." json:"responseHeaderTimeout,omitempty" toml:"responseHeaderTimeout,omitempty" yaml:"responseHeaderTimeout,omitempty" export:"true"`
|
ResponseHeaderTimeout ptypes.Duration `description:"The amount of time to wait for a server's response headers after fully writing the request (including its body, if any). If zero, no timeout exists." json:"responseHeaderTimeout,omitempty" toml:"responseHeaderTimeout,omitempty" yaml:"responseHeaderTimeout,omitempty" export:"true"`
|
||||||
IdleConnTimeout ptypes.Duration `description:"The maximum period for which an idle HTTP keep-alive connection will remain open before closing itself" json:"idleConnTimeout,omitempty" toml:"idleConnTimeout,omitempty" yaml:"idleConnTimeout,omitempty" export:"true"`
|
IdleConnTimeout ptypes.Duration `description:"The maximum period for which an idle HTTP keep-alive connection will remain open before closing itself." json:"idleConnTimeout,omitempty" toml:"idleConnTimeout,omitempty" yaml:"idleConnTimeout,omitempty" export:"true"`
|
||||||
|
ReadIdleTimeout ptypes.Duration `description:"The timeout after which a health check using ping frame will be carried out if no frame is received on the HTTP/2 connection. If zero, no health check is performed." json:"readIdleTimeout,omitempty" toml:"readIdleTimeout,omitempty" yaml:"readIdleTimeout,omitempty" export:"true"`
|
||||||
|
PingTimeout ptypes.Duration `description:"The timeout after which the HTTP/2 connection will be closed if a response to ping is not received." json:"pingTimeout,omitempty" toml:"pingTimeout,omitempty" yaml:"pingTimeout,omitempty" export:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaults sets the default values.
|
// SetDefaults sets the default values.
|
||||||
func (f *ForwardingTimeouts) SetDefaults() {
|
func (f *ForwardingTimeouts) SetDefaults() {
|
||||||
f.DialTimeout = ptypes.Duration(30 * time.Second)
|
f.DialTimeout = ptypes.Duration(30 * time.Second)
|
||||||
f.IdleConnTimeout = ptypes.Duration(90 * time.Second)
|
f.IdleConnTimeout = ptypes.Duration(90 * time.Second)
|
||||||
|
f.PingTimeout = ptypes.Duration(15 * time.Second)
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,8 @@ spec:
|
||||||
dialTimeout: 42
|
dialTimeout: 42
|
||||||
responseHeaderTimeout: 42s
|
responseHeaderTimeout: 42s
|
||||||
idleConnTimeout: 42ms
|
idleConnTimeout: 42ms
|
||||||
|
readIdleTimeout: 42s
|
||||||
|
pingTimeout: 42s
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: traefik.containo.us/v1alpha1
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
|
|
@ -340,6 +340,20 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client)
|
||||||
logger.Errorf("Error while reading IdleConnTimeout: %v", err)
|
logger.Errorf("Error while reading IdleConnTimeout: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if serversTransport.Spec.ForwardingTimeouts.ReadIdleTimeout != nil {
|
||||||
|
err := forwardingTimeout.ReadIdleTimeout.Set(serversTransport.Spec.ForwardingTimeouts.ReadIdleTimeout.String())
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("Error while reading ReadIdleTimeout: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if serversTransport.Spec.ForwardingTimeouts.PingTimeout != nil {
|
||||||
|
err := forwardingTimeout.PingTimeout.Set(serversTransport.Spec.ForwardingTimeouts.PingTimeout.String())
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("Error while reading PingTimeout: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
id := provider.Normalize(makeID(serversTransport.Namespace, serversTransport.Name))
|
id := provider.Normalize(makeID(serversTransport.Namespace, serversTransport.Name))
|
||||||
|
|
|
@ -3618,6 +3618,8 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
DialTimeout: ptypes.Duration(42 * time.Second),
|
DialTimeout: ptypes.Duration(42 * time.Second),
|
||||||
ResponseHeaderTimeout: ptypes.Duration(42 * time.Second),
|
ResponseHeaderTimeout: ptypes.Duration(42 * time.Second),
|
||||||
IdleConnTimeout: ptypes.Duration(42 * time.Millisecond),
|
IdleConnTimeout: ptypes.Duration(42 * time.Millisecond),
|
||||||
|
ReadIdleTimeout: ptypes.Duration(42 * time.Second),
|
||||||
|
PingTimeout: ptypes.Duration(42 * time.Second),
|
||||||
},
|
},
|
||||||
PeerCertURI: "foo://bar",
|
PeerCertURI: "foo://bar",
|
||||||
},
|
},
|
||||||
|
@ -3626,6 +3628,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
ForwardingTimeouts: &dynamic.ForwardingTimeouts{
|
ForwardingTimeouts: &dynamic.ForwardingTimeouts{
|
||||||
DialTimeout: ptypes.Duration(30 * time.Second),
|
DialTimeout: ptypes.Duration(30 * time.Second),
|
||||||
IdleConnTimeout: ptypes.Duration(90 * time.Second),
|
IdleConnTimeout: ptypes.Duration(90 * time.Second),
|
||||||
|
PingTimeout: ptypes.Duration(15 * time.Second),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -4873,6 +4876,8 @@ func TestCrossNamespace(t *testing.T) {
|
||||||
DialTimeout: 30000000000,
|
DialTimeout: 30000000000,
|
||||||
ResponseHeaderTimeout: 0,
|
ResponseHeaderTimeout: 0,
|
||||||
IdleConnTimeout: 90000000000,
|
IdleConnTimeout: 90000000000,
|
||||||
|
ReadIdleTimeout: 0,
|
||||||
|
PingTimeout: 15000000000,
|
||||||
},
|
},
|
||||||
DisableHTTP2: true,
|
DisableHTTP2: true,
|
||||||
},
|
},
|
||||||
|
@ -4904,6 +4909,8 @@ func TestCrossNamespace(t *testing.T) {
|
||||||
DialTimeout: 30000000000,
|
DialTimeout: 30000000000,
|
||||||
ResponseHeaderTimeout: 0,
|
ResponseHeaderTimeout: 0,
|
||||||
IdleConnTimeout: 90000000000,
|
IdleConnTimeout: 90000000000,
|
||||||
|
ReadIdleTimeout: 0,
|
||||||
|
PingTimeout: 15000000000,
|
||||||
},
|
},
|
||||||
DisableHTTP2: true,
|
DisableHTTP2: true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -43,13 +43,17 @@ type ServersTransportSpec struct {
|
||||||
|
|
||||||
// ForwardingTimeouts contains timeout configurations for forwarding requests to the backend servers.
|
// ForwardingTimeouts contains timeout configurations for forwarding requests to the backend servers.
|
||||||
type ForwardingTimeouts struct {
|
type ForwardingTimeouts struct {
|
||||||
// The amount of time to wait until a connection to a backend server can be established. If zero, no timeout exists.
|
// DialTimeout is the amount of time to wait until a connection to a backend server can be established. If zero, no timeout exists.
|
||||||
DialTimeout *intstr.IntOrString `json:"dialTimeout,omitempty"`
|
DialTimeout *intstr.IntOrString `json:"dialTimeout,omitempty"`
|
||||||
// The amount of time to wait for a server's response headers after fully writing the request (including its body, if any).
|
// ResponseHeaderTimeout is the amount of time to wait for a server's response headers after fully writing the request (including its body, if any).
|
||||||
// If zero, no timeout exists.
|
// If zero, no timeout exists.
|
||||||
ResponseHeaderTimeout *intstr.IntOrString `json:"responseHeaderTimeout,omitempty"`
|
ResponseHeaderTimeout *intstr.IntOrString `json:"responseHeaderTimeout,omitempty"`
|
||||||
// The maximum period for which an idle HTTP keep-alive connection will remain open before closing itself.
|
// IdleConnTimeout is the maximum period for which an idle HTTP keep-alive connection will remain open before closing itself.
|
||||||
IdleConnTimeout *intstr.IntOrString `json:"idleConnTimeout,omitempty"`
|
IdleConnTimeout *intstr.IntOrString `json:"idleConnTimeout,omitempty"`
|
||||||
|
// ReadIdleTimeout is the timeout after which a health check using ping frame will be carried out if no frame is received on the HTTP/2 connection. If zero, no health check is performed.
|
||||||
|
ReadIdleTimeout *intstr.IntOrString `json:"readIdleTimeout,omitempty"`
|
||||||
|
// PingTimeout is the timeout after which the HTTP/2 connection will be closed if a response to ping is not received.
|
||||||
|
PingTimeout *intstr.IntOrString `json:"pingTimeout,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
|
@ -214,6 +214,16 @@ func (in *ForwardingTimeouts) DeepCopyInto(out *ForwardingTimeouts) {
|
||||||
*out = new(intstr.IntOrString)
|
*out = new(intstr.IntOrString)
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
|
if in.ReadIdleTimeout != nil {
|
||||||
|
in, out := &in.ReadIdleTimeout, &out.ReadIdleTimeout
|
||||||
|
*out = new(intstr.IntOrString)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.PingTimeout != nil {
|
||||||
|
in, out := &in.PingTimeout, &out.PingTimeout
|
||||||
|
*out = new(intstr.IntOrString)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,16 +152,7 @@ func createRoundTripper(cfg *dynamic.ServersTransport) (http.RoundTripper, error
|
||||||
return transport, nil
|
return transport, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
transport.RegisterProtocol("h2c", &h2cTransportWrapper{
|
return newSmartRoundTripper(transport, cfg.ForwardingTimeouts)
|
||||||
Transport: &http2.Transport{
|
|
||||||
DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) {
|
|
||||||
return net.Dial(netw, addr)
|
|
||||||
},
|
|
||||||
AllowHTTP: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return newSmartRoundTripper(transport)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func createRootCACertPool(rootCAs []traefiktls.FileOrContent) *x509.CertPool {
|
func createRootCACertPool(rootCAs []traefiktls.FileOrContent) *x509.CertPool {
|
||||||
|
|
|
@ -1,33 +1,58 @@
|
||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||||
"golang.org/x/net/http/httpguts"
|
"golang.org/x/net/http/httpguts"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newSmartRoundTripper(transport *http.Transport) (http.RoundTripper, error) {
|
func newSmartRoundTripper(transport *http.Transport, forwardingTimeouts *dynamic.ForwardingTimeouts) (http.RoundTripper, error) {
|
||||||
transportHTTP1 := transport.Clone()
|
transportHTTP1 := transport.Clone()
|
||||||
|
|
||||||
err := http2.ConfigureTransport(transport)
|
transportHTTP2, err := http2.ConfigureTransports(transport)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if forwardingTimeouts != nil {
|
||||||
|
transportHTTP2.ReadIdleTimeout = time.Duration(forwardingTimeouts.ReadIdleTimeout)
|
||||||
|
transportHTTP2.PingTimeout = time.Duration(forwardingTimeouts.PingTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
transportH2C := &h2cTransportWrapper{
|
||||||
|
Transport: &http2.Transport{
|
||||||
|
DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
|
||||||
|
return net.Dial(network, addr)
|
||||||
|
},
|
||||||
|
AllowHTTP: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if forwardingTimeouts != nil {
|
||||||
|
transportH2C.ReadIdleTimeout = time.Duration(forwardingTimeouts.ReadIdleTimeout)
|
||||||
|
transportH2C.PingTimeout = time.Duration(forwardingTimeouts.PingTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
transport.RegisterProtocol("h2c", transportH2C)
|
||||||
|
|
||||||
return &smartRoundTripper{
|
return &smartRoundTripper{
|
||||||
http2: transport,
|
http2: transport,
|
||||||
http: transportHTTP1,
|
http: transportHTTP1,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// smartRoundTripper implements RoundTrip while making sure that HTTP/2 is not used
|
||||||
|
// with protocols that start with a Connection Upgrade, such as SPDY or Websocket.
|
||||||
type smartRoundTripper struct {
|
type smartRoundTripper struct {
|
||||||
http2 *http.Transport
|
http2 *http.Transport
|
||||||
http *http.Transport
|
http *http.Transport
|
||||||
}
|
}
|
||||||
|
|
||||||
// smartRoundTripper implements RoundTrip while making sure that HTTP/2 is not used
|
|
||||||
// with protocols that start with a Connection Upgrade, such as SPDY or Websocket.
|
|
||||||
func (m *smartRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
func (m *smartRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
// If we have a connection upgrade, we don't use HTTP/2
|
// If we have a connection upgrade, we don't use HTTP/2
|
||||||
if httpguts.HeaderValuesContainsToken(req.Header["Connection"], "Upgrade") {
|
if httpguts.HeaderValuesContainsToken(req.Header["Connection"], "Upgrade") {
|
||||||
|
|
Loading…
Reference in a new issue