aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@golang.org>2016-01-09 15:34:56 -0800
committerBrad Fitzpatrick <bradfitz@golang.org>2016-01-10 01:37:18 +0000
commit9ee72f424c83c07e53fde15e5eba9e4b6b02dee4 (patch)
treeb34a022245c6ac623efe57c0d90493ea05696a16
parent2747ca351efc2b9b0f1d0a7988c752f859feebb7 (diff)
downloadgo-9ee72f424c83c07e53fde15e5eba9e4b6b02dee4.tar.gz
go-9ee72f424c83c07e53fde15e5eba9e4b6b02dee4.zip
net/http: update bundled http2
Updates http2 to x/net git rev 0e6d34ef942 for https://golang.org/cl/18472 which means we'll get to delete a ton of grpc-go code and just use the standard library's HTTP client instead. Also, the comments in this CL aren't entirely accurate it turns out. RFC 2616 says: "The Trailer header field can be used to indicate which header fields are included in a trailer (see section 14.40)." And 14.40: " An HTTP/1.1 message SHOULD include a Trailer header field in a message using chunked transfer-coding with a non-empty trailer. Doing so allows the recipient to know which header fields to expect in the trailer. If no Trailer header field is present, the trailer SHOULD NOT include any header fields. See section 3.6.1 for restrictions on the use of trailer fields in a "chunked" transfer-coding." So it's really a SHOULD more than a MUST. And gRPC (at least Google's server) doesn't predeclare "grpc-status" ahead of time in a Trailer Header, so we'll be lenient. We were too strict anyway. It's also not a concern for the Go client we have a different place to populate the Trailers, and it won't confuse clients which aren't looking for them. The ResponseWriter server side is more complicated (and strict), though, since we don't want to widen the ResponseWriter interface. So the Go server still requires that you predeclare Trailers. Change-Id: Ia2defc11a2469fb8570ecfabb8453537121084eb Reviewed-on: https://go-review.googlesource.com/18473 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
-rw-r--r--src/net/http/h2_bundle.go22
1 files changed, 15 insertions, 7 deletions
diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go
index 69fad37bec..4be56f50c5 100644
--- a/src/net/http/h2_bundle.go
+++ b/src/net/http/h2_bundle.go
@@ -24,6 +24,7 @@ import (
"encoding/binary"
"errors"
"fmt"
+ "golang.org/x/net/http2/hpack"
"io"
"io/ioutil"
"log"
@@ -37,8 +38,6 @@ import (
"strings"
"sync"
"time"
-
- "golang.org/x/net/http2/hpack"
)
// ClientConnPool manages a pool of HTTP/2 client connections.
@@ -4348,8 +4347,8 @@ type http2clientStream struct {
pastHeaders bool // got HEADERS w/ END_HEADERS
pastTrailers bool // got second HEADERS frame w/ END_HEADERS
- trailer Header // accumulated trailers
- resTrailer Header // client's Response.Trailer
+ trailer Header // accumulated trailers
+ resTrailer *Header // client's Response.Trailer
}
// awaitRequestCancel runs in its own goroutine and waits for the user
@@ -5255,7 +5254,7 @@ func (rl *http2clientConnReadLoop) processHeaderBlockFragment(frag []byte, strea
}
}
- cs.resTrailer = res.Trailer
+ cs.resTrailer = &res.Trailer
rl.activeRes[cs.ID] = cs
cs.resc <- http2resAndError{res: res}
rl.nextRes = nil
@@ -5383,7 +5382,11 @@ func (rl *http2clientConnReadLoop) endStream(cs *http2clientStream) {
func (cs *http2clientStream) copyTrailers() {
for k, vv := range cs.trailer {
- cs.resTrailer[k] = vv
+ t := cs.resTrailer
+ if *t == nil {
+ *t = make(Header)
+ }
+ (*t)[k] = vv
}
}
@@ -5583,7 +5586,12 @@ func (rl *http2clientConnReadLoop) onNewTrailerField(cs *http2clientStream, f hp
}
key := CanonicalHeaderKey(f.Name)
- if _, ok := cs.resTrailer[key]; ok {
+
+ // The spec says one must predeclare their trailers but in practice
+ // popular users (which is to say the only user we found) do not so we
+ // violate the spec and accept all of them.
+ const acceptAllTrailers = true
+ if _, ok := (*cs.resTrailer)[key]; ok || acceptAllTrailers {
if cs.trailer == nil {
cs.trailer = make(Header)
}