-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net/http: support unencrypted HTTP/2 (h2c) #67816
Comments
https://pkg.go.dev/golang.org/x/net/http2/h2c currently states:
Would that be fixed ? |
Since I'm proposing to only support HTTP/2 with prior knowledge, not |
A few more details on with-prior-knowledge vs. upgrade: There are two ways to start an unencrypted HTTP/2 connection. One mechanism is called "HTTP/2 with prior knowledge", in which the client knows the server supports unencrypted HTTP/2. The client opens an unencrypted TCP connection and starts the HTTP/2 protocol, beginning by sending the HTTP/2 client preface. This is just HTTP/2, only over an unencrypted connection rather than TLS. The other mechanism involves starting a connection as HTTP/1 and negotiating an upgrade to HTTP/2. The client sends an HTTP/1 request with an This is why the We could do something more sophisticated. For example, perhaps we could accept However, it isn't clear that this complexity is worth it. While the general idea of "use HTTP/2 if you can, fall back to HTTP/1 if you can't" seems reasonable, I don't know of any actual use cases. So far as I can tell, previous requests for unencrypted HTTP/2 have been for scenarios where the user controls both endpoints, or where the user needs to interact with an endpoint that only speaks HTTP/2. I think the right choice is to support with-prior-knowledge only, at least to start with, especially since the |
This proposal has been added to the active column of the proposals project |
This seems reasonable modulo the answer to #67814. |
If we adopt the suggestion in #67814 (comment), the API change here would be:
|
Have all remaining concerns about this proposal been addressed? The proposal is to first adopt #67814 and then add
The default will be to not support unencrypted HTTP/2 unless explicitly opted in. |
Based on the discussion above, this proposal seems like a likely accept. The proposal is to first adopt #67814 and then add
The default will be to not support unencrypted HTTP/2 unless explicitly opted in. |
No change in consensus, so accepted. 🎉 The proposal is to first adopt #67814 and then add
The default will be to not support unencrypted HTTP/2 unless explicitly opted in. |
Change https://go.dev/cl/625175 mentions this issue: |
Change https://go.dev/cl/622976 mentions this issue: |
Allow net/http to pass unencrypted net.Conns to Server/Transport. We don't have an existing way to pass a conn other than a *tls.Conn into this package, so (ab)use TLSNextProto to pass unencrypted connections: The http2 package adds an "unencrypted_http2" entry to the TLSNextProto maps. The net/http package calls this function with a *tls.Conn wrapping a net.Conn with an UnencryptedNetConn method returning the underlying, unencrypted net.Conn. For golang/go#67816 Change-Id: I31f9c1ba31a17c82c8ed651382bd94193acf09b9 Reviewed-on: https://go-review.googlesource.com/c/net/+/625175 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Add an UnencryptedHTTP2 protocol value. Both Server and Transport implement "HTTP/2 with prior knowledge" as described in RFC 9113, section 3.3. Neither supports the deprecated HTTP/2 upgrade mechanism (RFC 7540, section 3.2 "h2c"). For Server, UnencryptedHTTP2 controls whether the server will accept HTTP/2 connections on unencrypted ports. When enabled, the server checks new connections for the HTTP/2 preface and routes them appropriately. For Transport, enabling UnencryptedHTTP2 and disabling HTTP1 causes http:// requests to be made over unencrypted HTTP/2 connections. For #67816 Change-Id: I2763c4cdec1c2bc6bb8157edb93b94377de8a59b Reviewed-on: https://go-review.googlesource.com/c/go/+/622976 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Change https://go.dev/cl/630976 mentions this issue: |
Reopening to remember to remove a t.Skip in net/http after the HTTP/2 bundle is updated. |
Change https://go.dev/cl/631035 mentions this issue: |
For #67816 Change-Id: I9ba3a245d6b18758944ca5e206a15892b2aa6028 Reviewed-on: https://go-review.googlesource.com/c/go/+/630976 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org> Auto-Submit: Damien Neil <dneil@google.com>
A part of the keeping Go's vendored dependencies and generated code up to date. This updates h2_bundle.go with unencrypted HTTP/2 support. For #36905. For #67816. [git-generate] cd src go get golang.org/x/net@v0.31.0 go mod tidy go mod vendor cd cmd go get golang.org/x/net@v0.31.0 go mod tidy go mod vendor go generate -run=bundle std Change-Id: I2b77f651b990f260fbe7d551c7a819518f1c983f Reviewed-on: https://go-review.googlesource.com/c/go/+/631035 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Damien Neil <dneil@google.com> Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
Change https://go.dev/cl/631037 mentions this issue: |
This issue is part of a project to move
x/net/http2
intostd
: #67810This proposal depends on the version selection API proposed in #67814.
The
net/http
package does not directly support unencrypted HTTP/2, sometimes referred to as "h2c".Users may send HTTP/2 requests over an unencrypted connection by setting
http2.Transport.AllowHTTP
and providing aDialTLS
function which opens an unencrypted connection. Users may accept unencrypted HTTP/2 requests by using the golang.org/x/net/http2/h2c package.Neither of these mechanisms is very clean: Returning an unencrypted connection from
DialTLS
is unfortunate, and the interactions betweennet/http
,h2c
, andgolang.org/x/net/http2
are fairly complicated.I propose adding support for unencrypted HTTP/2 as a first-class feature to
net/http
.HTTP/2 will be enabled by a new
http.Protocol
value:When
Server.Protocol
containsUnencryptedHTTP2
, the server will accept HTTP/2 requests on its unencrypted port(s).When
Transport.Protocol
containsUnencryptedHTTP2
but notHTTP1
, the transport will use unencrypted HTTP/2 for requests forhttp://
URLs ("Starting HTTP/2 with prior knowledge", RFC 9113 Section 3.3).The HTTP/2 http2.Transport.AllowHTTP setting controls whether the transport permits requests using the
http://
scheme. WhenProtocols
containsUnencryptedHTTP1
, the transport will ignore this setting and always permithttp://
requests.Upgrade: h2c
RFC 7540 Section 3.2 defines a mechanism for upgrading an HTTP/1 request to HTTP/2. The client sends an HTTP/1 request with a
Upgrade: h2c
header and aHttp2-Settings
header containing the proposed HTTP/2 settings. The server may respond with101 Switching Protocols
and convert the connection to HTTP/2.RFC 9113 Section 3.1 deprecates this upgrade mechanism, stating: "This usage was never widely deployed and is deprecated by this document."
(For encrypted connections, the protocol is negotiated using TLS ALPN and the
Upgrade
header is not used.)The
golang.org/x/net/http2/h2c
package supportsUpgrade: h2c
on server connections.We do not currently support
Upgrade: h2c
for client connections. (This means that theh2c
package's support forUpgrade: h2c
has no test coverage, since we don't have any ability to make a client connection to exercise it with.)I propose that we only add support for unencrypted HTTP/2 with prior knowledge, not
Upgrade: h2c
. Connection upgrade is complicated, since it requires us to convert a connection from one protocol to another mid-request. It comes with surprising limitations that are difficult to describe. (The initial HTTP/1 request body on an upgraded connection must be sent in its entirety before the client can begin transmitting HTTP/2 frames.) Most requests for unencrypted HTTP/2 focus on cases where the user has full control of both endpoints and can use prior knowledge. The current lack of support for client-side upgrade means that any users depending on it are doing so with non-Go clients. And, of course, the mechanism is deprecated.The text was updated successfully, but these errors were encountered: