Skip to content

Commit 445eead

Browse files
neildgopherbot
authored andcommitted
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 <[email protected]> Auto-Submit: Damien Neil <[email protected]> Reviewed-by: Antonio Ojea <[email protected]> Reviewed-by: Jonathan Amsterdam <[email protected]>
1 parent 5566b43 commit 445eead

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
@@ -2088,10 +2088,6 @@ func validateHeaders(hdrs http.Header) string {
20882088

20892089
var errNilRequestURL = errors.New("http2: Request.URI is nil")
20902090

2091-
func isNormalConnect(req *http.Request) bool {
2092-
return req.Method == "CONNECT" && req.Header.Get(":protocol") == ""
2093-
}
2094-
20952091
// requires cc.wmu be held.
20962092
func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) {
20972093
cc.hbuf.Reset()
@@ -2111,8 +2107,17 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
21112107
return nil, errors.New("http2: invalid Host header")
21122108
}
21132109

2110+
// isNormalConnect is true if this is a non-extended CONNECT request.
2111+
isNormalConnect := false
2112+
protocol := req.Header.Get(":protocol")
2113+
if req.Method == "CONNECT" && protocol == "" {
2114+
isNormalConnect = true
2115+
} else if protocol != "" && req.Method != "CONNECT" {
2116+
return nil, errors.New("http2: invalid :protocol header in non-CONNECT request")
2117+
}
2118+
21142119
var path string
2115-
if !isNormalConnect(req) {
2120+
if !isNormalConnect {
21162121
path = req.URL.RequestURI()
21172122
if !validPseudoPath(path) {
21182123
orig := path
@@ -2149,10 +2154,13 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
21492154
m = http.MethodGet
21502155
}
21512156
f(":method", m)
2152-
if !isNormalConnect(req) {
2157+
if !isNormalConnect {
21532158
f(":path", path)
21542159
f(":scheme", req.URL.Scheme)
21552160
}
2161+
if protocol != "" {
2162+
f(":protocol", protocol)
2163+
}
21562164
if trailers != "" {
21572165
f("trailer", trailers)
21582166
}
@@ -2209,6 +2217,9 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
22092217
}
22102218
}
22112219
continue
2220+
} else if k == ":protocol" {
2221+
// :protocol pseudo-header was already sent above.
2222+
continue
22122223
}
22132224

22142225
for _, v := range vv {

http2/transport_test.go

+6
Original file line numberDiff line numberDiff line change
@@ -5872,6 +5872,9 @@ func TestExtendedConnectClientWithServerSupport(t *testing.T) {
58725872
pwDone := make(chan struct{})
58735873
req, _ := http.NewRequest("CONNECT", ts.URL, pr)
58745874
req.Header.Set(":protocol", "extended-connect")
5875+
req.Header.Set("X-A", "A")
5876+
req.Header.Set("X-B", "B")
5877+
req.Header.Set("X-C", "C")
58755878
go func() {
58765879
pw.Write([]byte("hello, extended connect"))
58775880
pw.Close()
@@ -5905,6 +5908,9 @@ func TestExtendedConnectClientWithoutServerSupport(t *testing.T) {
59055908
pwDone := make(chan struct{})
59065909
req, _ := http.NewRequest("CONNECT", ts.URL, pr)
59075910
req.Header.Set(":protocol", "extended-connect")
5911+
req.Header.Set("X-A", "A")
5912+
req.Header.Set("X-B", "B")
5913+
req.Header.Set("X-C", "C")
59085914
go func() {
59095915
pw.Write([]byte("hello, extended connect"))
59105916
pw.Close()

0 commit comments

Comments
 (0)