Skip to content

net/http: HTTP version selection API #67814

Closed
@neild

Description

@neild

This issue is part of a project to move x/net/http2 into std: #67810

I propose adding a new mechanism for selecting what HTTP versions will be used by a net/http Server or Transport.

// A Protocol is a bitmask of HTTP protocols.
type Protocol uint64

// Contains reports whether p contains all protocols in v.
func (p Protocol) Contains(v Protocol) bool { return p&v != 0 }

const (
        // HTTP1 is the HTTP/1.0 and HTTP/1.1 protocols.
        // HTTP1 is supported on both unsecured TCP and secured TLS connections.
        HTTP1 Protocol = (1 << iota)

        // HTTP2 is the HTTP/2 protocol over a TLS connection.
        HTTP2
)

type Server { // contains unchanged fields
        // Protocols is the set of protocols accepted by the server.
        // If the set is empty, the default is usually HTTP/1 and HTTP/2.
        // The default is HTTP/1 only if TLSNextProto is non-nil
        // and does not contain an "h2" entry.
        Protocols Protocol
}

type Transport { // contains unchanged fields
        // Protocols is the set of protocols supported by the transport.
        // If zero, the default is usually HTTP/1 only.
        // The default is HTTP/1 and HTTP/2 if ForceAttemptHTTP2 is true,
        // or if TLSNextProto contains an "h2" entry.
        Protocols Protocol
}

Currently, by default

  • a net/http server listening on a TLS connection will accept both HTTP/1 and HTTP/2 requests;
  • a net/http transport will use HTTP/1 for https requests (never HTTP/2); and
  • net/http.DefaultTransport will use HTTP/2 when available and HTTP/1 otherwise for https requests.

Users may disable HTTP/2 support by setting Server.TLSNextProto or Transport.TLSNextProto to an empty map.

Users may enable HTTP/2 support on a transport by setting Transport.ForceAttemptHTTP2.

Users may disable HTTP/1 support by importing golang.org/x/net/http2 using an http2.Server or http2.Transport directly.

The net/http package does not currently directly support HTTP/3, but if and when it does, there will need to be a mechanism for enabling or disabling HTTP/3.

The existing APIs for selecting a protocol version are confusing, inconsistent, expose internal implementation details, and don't generalize well to additional protocol versions. The above proposal replaces them with a single, clear mechanism that allows for future expansion.

Example usage:

s := &http.Server{}
s.Protocols = HTTP1 // disable HTTP/2 support

tr := &http.Transport{}
tr.Protocols = HTTP1 | HTTP2 // enable HTTP/2 support

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Accepted

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions