Skip to content

net/http: Cloning a transport and disabling http2 makes requests fail.  #50571

Closed
@cyriltovena

Description

@cyriltovena

What version of Go are you using (go version)?

$ go version
go version go1.17.2 darwin/amd64

Does this issue reproduce with the latest release?

Not sure I didn't try

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
O111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/ctovena/Library/Caches/go-build"
GOENV="/Users/ctovena/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/ctovena/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/ctovena/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/Cellar/go/1.17.2/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.17.2/libexec/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.17.2"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/ctovena/go/src/github.com/grafana/loki/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/vc/_6f73v6s6yj1qnnzk60c8b9m0000gn/T/go-build2408466595=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

I wanted to disable http2 for my http client, by using the tr.TLSNextProto as stated in the doc. However when it's done from a cloned transport it seems to break the transport.

package main

import (
	"crypto/tls"
	"fmt"
	"net"
	"net/http"
	"time"
)

func main() {
	tr := http.DefaultTransport.(*http.Transport).Clone()
	tr.TLSNextProto = make(map[string]func(string, *tls.Conn) http.RoundTripper)

	req, err := http.NewRequest("GET", "https://google.com", http.NoBody)
	if err != nil {
		panic(err)
	}
	_, err = tr.RoundTrip(req)
	if err != nil {
		fmt.Println("cloned error:", err)
	}

	tr = &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		DialContext: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
		}).DialContext,
		ForceAttemptHTTP2:     true,
		MaxIdleConns:          100,
		IdleConnTimeout:       90 * time.Second,
		TLSHandshakeTimeout:   10 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
	}
	tr.TLSNextProto = make(map[string]func(string, *tls.Conn) http.RoundTripper)
	_, err = tr.RoundTrip(req)
	if err != nil {
		fmt.Println("error:", err)
	}
}

When using a new transport (not cloned) it works correctly.

What did you expect to see?

My transport to correctly work and use HTTP1.1

What did you see instead?

Some http2 handshake error.

net/http: HTTP/1.x transport connection broken: malformed HTTP response \"\\x00\\x00\\x12\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00d\\x00\\x04\\x00\\x10\\x00\\x00\\x00\\x06\\x00\\x01\\x00\\x00\\x00\\x00\\x04\\b\\x00\\x00\\x00\\x00\\x00\\x00\\x0f\\x00\\x01\\x00\\x00\\x1e\\a\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01http2_handshake_failed\"\n\n"

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions