Skip to content

net/http: Transport's automatic http2 too aggressive? #14275

Closed
@bradfitz

Description

@bradfitz

I was just investigating an internal bug report where Go 1.6 broke user's code. The user's code was like:

    transport := &http.Transport{
        TLSClientConfig:     &tls.Config{},
    }
    transport.Dial = func(network, addr string) (net.Conn, error) {
        if isHTTPSProxy(addr) {
            return tls.Dial(network, addr, transport.TLSClientConfig)
        }
        return dialer.Dial(network, addr)
    }

In Go 1.5, that TLSClientConfig was untouched. In Go 1.6, the first call to RoundTrip calls http2.ConfigureTransport, which mutates the Transport.TLSClientConfig.

In this user's case, that meant they sent a TLS NextProto of h2 to the peer, which was accepted, and the peer started speaking http2, but the net/http was trying to make a normal http (not https) request, so http2 wasn't even considered. Then Go's transport was speaking http/1.1 and the server thought it was speaking http2. Fail.

Perhaps we need to rethink how the automatic upgrade to http2 works in Go 1.7.

Maybe as an intermediate conservative step for Go 1.6 we don't auto-enable http2 on Transports where TLSClientConfig is populated, so it doesn't surprise people by being mutated. I was also considering disabling it if Dial or DialTLS are populated, but http.DefaultTransport sets Dial, and I don't want to special-case looking at whether the transport == DefaultTransport.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions