mirror of
https://github.com/golang/net.git
synced 2026-04-01 02:47:08 +09:00
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>
This commit is contained in:
committed by
Gopher Robot
parent
5566b43feb
commit
445eead606
@@ -2088,10 +2088,6 @@ func validateHeaders(hdrs http.Header) string {
|
||||
|
||||
var errNilRequestURL = errors.New("http2: Request.URI is nil")
|
||||
|
||||
func isNormalConnect(req *http.Request) bool {
|
||||
return req.Method == "CONNECT" && req.Header.Get(":protocol") == ""
|
||||
}
|
||||
|
||||
// requires cc.wmu be held.
|
||||
func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) {
|
||||
cc.hbuf.Reset()
|
||||
@@ -2111,8 +2107,17 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
|
||||
return nil, errors.New("http2: invalid Host header")
|
||||
}
|
||||
|
||||
// isNormalConnect is true if this is a non-extended CONNECT request.
|
||||
isNormalConnect := false
|
||||
protocol := req.Header.Get(":protocol")
|
||||
if req.Method == "CONNECT" && protocol == "" {
|
||||
isNormalConnect = true
|
||||
} else if protocol != "" && req.Method != "CONNECT" {
|
||||
return nil, errors.New("http2: invalid :protocol header in non-CONNECT request")
|
||||
}
|
||||
|
||||
var path string
|
||||
if !isNormalConnect(req) {
|
||||
if !isNormalConnect {
|
||||
path = req.URL.RequestURI()
|
||||
if !validPseudoPath(path) {
|
||||
orig := path
|
||||
@@ -2149,10 +2154,13 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
|
||||
m = http.MethodGet
|
||||
}
|
||||
f(":method", m)
|
||||
if !isNormalConnect(req) {
|
||||
if !isNormalConnect {
|
||||
f(":path", path)
|
||||
f(":scheme", req.URL.Scheme)
|
||||
}
|
||||
if protocol != "" {
|
||||
f(":protocol", protocol)
|
||||
}
|
||||
if trailers != "" {
|
||||
f("trailer", trailers)
|
||||
}
|
||||
@@ -2209,6 +2217,9 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
|
||||
}
|
||||
}
|
||||
continue
|
||||
} else if k == ":protocol" {
|
||||
// :protocol pseudo-header was already sent above.
|
||||
continue
|
||||
}
|
||||
|
||||
for _, v := range vv {
|
||||
|
||||
@@ -5872,6 +5872,9 @@ func TestExtendedConnectClientWithServerSupport(t *testing.T) {
|
||||
pwDone := make(chan struct{})
|
||||
req, _ := http.NewRequest("CONNECT", ts.URL, pr)
|
||||
req.Header.Set(":protocol", "extended-connect")
|
||||
req.Header.Set("X-A", "A")
|
||||
req.Header.Set("X-B", "B")
|
||||
req.Header.Set("X-C", "C")
|
||||
go func() {
|
||||
pw.Write([]byte("hello, extended connect"))
|
||||
pw.Close()
|
||||
@@ -5905,6 +5908,9 @@ func TestExtendedConnectClientWithoutServerSupport(t *testing.T) {
|
||||
pwDone := make(chan struct{})
|
||||
req, _ := http.NewRequest("CONNECT", ts.URL, pr)
|
||||
req.Header.Set(":protocol", "extended-connect")
|
||||
req.Header.Set("X-A", "A")
|
||||
req.Header.Set("X-B", "B")
|
||||
req.Header.Set("X-C", "C")
|
||||
go func() {
|
||||
pw.Write([]byte("hello, extended connect"))
|
||||
pw.Close()
|
||||
|
||||
Reference in New Issue
Block a user