Skip to content

Commit 9a960c8

Browse files
neildgopherbot
authored andcommitted
[internal-branch.go1.24-vendor] http2: encode :protocol pseudo-header before regular headers
HTTP/2 requires that pseudo-headers (which start with : and are used to pass information other than the regular request headers) be encoded before all regular headers. The x/net/http2 Transport's extended CONNECT support is enabled by the user setting a ":protocol" header in the Request. This header matches the pseudo-header that will be sent on the wire. Ensure that the :protocol pseudo-header is sent before any regular headers. For golang/go#70728 Change-Id: I70de7ad524ab9457d6dfb61cb3fabe3d53c6b39b Reviewed-on: https://go-review.googlesource.com/c/net/+/641476 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Damien Neil <dneil@google.com> Reviewed-by: Antonio Ojea <aojea@google.com> Reviewed-by: Jonathan Amsterdam <jba@google.com> (cherry picked from commit 445eead) Reviewed-on: https://go-review.googlesource.com/c/net/+/643256 Auto-Submit: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
1 parent 68c5fdd commit 9a960c8

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

http2/transport.go

+17-6
Original file line numberDiff line numberDiff line change
@@ -2084,10 +2084,6 @@ func validateHeaders(hdrs http.Header) string {
20842084

20852085
var errNilRequestURL = errors.New("http2: Request.URI is nil")
20862086

2087-
func isNormalConnect(req *http.Request) bool {
2088-
return req.Method == "CONNECT" && req.Header.Get(":protocol") == ""
2089-
}
2090-
20912087
// requires cc.wmu be held.
20922088
func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) {
20932089
cc.hbuf.Reset()
@@ -2107,8 +2103,17 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
21072103
return nil, errors.New("http2: invalid Host header")
21082104
}
21092105

2106+
// isNormalConnect is true if this is a non-extended CONNECT request.
2107+
isNormalConnect := false
2108+
protocol := req.Header.Get(":protocol")
2109+
if req.Method == "CONNECT" && protocol == "" {
2110+
isNormalConnect = true
2111+
} else if protocol != "" && req.Method != "CONNECT" {
2112+
return nil, errors.New("http2: invalid :protocol header in non-CONNECT request")
2113+
}
2114+
21102115
var path string
2111-
if !isNormalConnect(req) {
2116+
if !isNormalConnect {
21122117
path = req.URL.RequestURI()
21132118
if !validPseudoPath(path) {
21142119
orig := path
@@ -2145,10 +2150,13 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
21452150
m = http.MethodGet
21462151
}
21472152
f(":method", m)
2148-
if !isNormalConnect(req) {
2153+
if !isNormalConnect {
21492154
f(":path", path)
21502155
f(":scheme", req.URL.Scheme)
21512156
}
2157+
if protocol != "" {
2158+
f(":protocol", protocol)
2159+
}
21522160
if trailers != "" {
21532161
f("trailer", trailers)
21542162
}
@@ -2205,6 +2213,9 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
22052213
}
22062214
}
22072215
continue
2216+
} else if k == ":protocol" {
2217+
// :protocol pseudo-header was already sent above.
2218+
continue
22082219
}
22092220

22102221
for _, v := range vv {

http2/transport_test.go

+6
Original file line numberDiff line numberDiff line change
@@ -5840,6 +5840,9 @@ func TestExtendedConnectClientWithServerSupport(t *testing.T) {
58405840
pwDone := make(chan struct{})
58415841
req, _ := http.NewRequest("CONNECT", ts.URL, pr)
58425842
req.Header.Set(":protocol", "extended-connect")
5843+
req.Header.Set("X-A", "A")
5844+
req.Header.Set("X-B", "B")
5845+
req.Header.Set("X-C", "C")
58435846
go func() {
58445847
pw.Write([]byte("hello, extended connect"))
58455848
pw.Close()
@@ -5873,6 +5876,9 @@ func TestExtendedConnectClientWithoutServerSupport(t *testing.T) {
58735876
pwDone := make(chan struct{})
58745877
req, _ := http.NewRequest("CONNECT", ts.URL, pr)
58755878
req.Header.Set(":protocol", "extended-connect")
5879+
req.Header.Set("X-A", "A")
5880+
req.Header.Set("X-B", "B")
5881+
req.Header.Set("X-C", "C")
58765882
go func() {
58775883
pw.Write([]byte("hello, extended connect"))
58785884
pw.Close()

0 commit comments

Comments
 (0)