diff --git a/build.Dockerfile b/build.Dockerfile index e7d682e44..aa77cac19 100644 --- a/build.Dockerfile +++ b/build.Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.13-alpine +FROM golang:1.14-alpine RUN apk --update upgrade \ && apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \ @@ -19,7 +19,7 @@ RUN mkdir -p /usr/local/bin \ && chmod +x /usr/local/bin/go-bindata # Download golangci-lint binary to bin folder in $GOPATH -RUN curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.23.0 +RUN curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.23.8 # Download golangci-lint and misspell binary to bin folder in $GOPATH RUN GO111MODULE=off go get github.com/client9/misspell/cmd/misspell diff --git a/docs/content/contributing/building-testing.md b/docs/content/contributing/building-testing.md index 1f04745dc..1f1080a3a 100644 --- a/docs/content/contributing/building-testing.md +++ b/docs/content/contributing/building-testing.md @@ -60,7 +60,7 @@ PRE_TARGET= make test-unit Requirements: -- `go` v1.13+ +- `go` v1.14+ - environment variable `GO111MODULE=on` - [go-bindata](https://github.com/containous/go-bindata) `GO111MODULE=off go get -u github.com/containous/go-bindata/...` diff --git a/exp.Dockerfile b/exp.Dockerfile index 730db9a40..c02db50ad 100644 --- a/exp.Dockerfile +++ b/exp.Dockerfile @@ -12,7 +12,7 @@ RUN npm install RUN npm run build # BUILD -FROM golang:1.13-alpine as gobuild +FROM golang:1.14-alpine as gobuild RUN apk --update upgrade \ && apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \ diff --git a/go.mod b/go.mod index 4fb8c63c6..b41e14a9b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/containous/traefik/v2 -go 1.13 +go 1.14 require ( github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect diff --git a/pkg/server/service/roundtripper.go b/pkg/server/service/roundtripper.go index f232049a6..715d5d5c2 100644 --- a/pkg/server/service/roundtripper.go +++ b/pkg/server/service/roundtripper.go @@ -23,12 +23,12 @@ func (t *h2cTransportWrapper) RoundTrip(req *http.Request) (*http.Response, erro return t.Transport.RoundTrip(req) } -// createHTTPTransport creates an http.Transport configured with the Transport configuration settings. +// createRoundtripper creates an http.Roundtripper configured with the Transport configuration settings. // For the settings that can't be configured in Traefik it uses the default http.Transport settings. // An exception to this is the MaxIdleConns setting as we only provide the option MaxIdleConnsPerHost // in Traefik at this point in time. Setting this value to the default of 100 could lead to confusing // behavior and backwards compatibility issues. -func createHTTPTransport(transportConfiguration *static.ServersTransport) (*http.Transport, error) { +func createRoundtripper(transportConfiguration *static.ServersTransport) (http.RoundTripper, error) { if transportConfiguration == nil { return nil, errors.New("no transport configuration given") } @@ -66,25 +66,26 @@ func createHTTPTransport(transportConfiguration *static.ServersTransport) (*http transport.IdleConnTimeout = time.Duration(transportConfiguration.ForwardingTimeouts.IdleConnTimeout) } - if transportConfiguration.InsecureSkipVerify { - transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} - } - - if len(transportConfiguration.RootCAs) > 0 { + if transportConfiguration.InsecureSkipVerify || len(transportConfiguration.RootCAs) > 0 { transport.TLSClientConfig = &tls.Config{ - RootCAs: createRootCACertPool(transportConfiguration.RootCAs), + InsecureSkipVerify: transportConfiguration.InsecureSkipVerify, + RootCAs: createRootCACertPool(transportConfiguration.RootCAs), } } - err := http2.ConfigureTransport(transport) + smartTransport, err := newSmartRoundTripper(transport) if err != nil { return nil, err } - return transport, nil + return smartTransport, nil } func createRootCACertPool(rootCAs []traefiktls.FileOrContent) *x509.CertPool { + if len(rootCAs) == 0 { + return nil + } + roots := x509.NewCertPool() for _, cert := range rootCAs { @@ -100,7 +101,7 @@ func createRootCACertPool(rootCAs []traefiktls.FileOrContent) *x509.CertPool { } func setupDefaultRoundTripper(conf *static.ServersTransport) http.RoundTripper { - transport, err := createHTTPTransport(conf) + transport, err := createRoundtripper(conf) if err != nil { log.WithoutContext().Errorf("Could not configure HTTP Transport, fallbacking on default transport: %v", err) return http.DefaultTransport diff --git a/pkg/server/service/smart_roundtripper.go b/pkg/server/service/smart_roundtripper.go new file mode 100644 index 000000000..9a3028720 --- /dev/null +++ b/pkg/server/service/smart_roundtripper.go @@ -0,0 +1,38 @@ +package service + +import ( + "net/http" + + "golang.org/x/net/http/httpguts" + "golang.org/x/net/http2" +) + +func newSmartRoundTripper(transport *http.Transport) (http.RoundTripper, error) { + transportHTTP1 := transport.Clone() + + err := http2.ConfigureTransport(transport) + if err != nil { + return nil, err + } + + return &smartRoundTripper{ + http2: transport, + http: transportHTTP1, + }, nil +} + +type smartRoundTripper struct { + http2 *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) { + // If we have a connection upgrade, we don't use HTTP/2 + if httpguts.HeaderValuesContainsToken(req.Header["Connection"], "Upgrade") { + return m.http.RoundTrip(req) + } + + return m.http2.RoundTrip(req) +}