• Brad Fitzpatrick's avatar
    http2: add mechanism to send undeclared Trailers mid handler · d513e585
    Brad Fitzpatrick authored
    This adds a way for http.Handlers to set trailers after the header has
    already been flushed. This comment from the code explains:
    
    // promoteUndeclaredTrailers permits http.Handlers to set trailers
    // after the header has already been flushed. Because the Go
    // ResponseWriter interface has no way to set Trailers (only the
    // Header), and because we didn't want to expand the ResponseWriter
    // interface, and because nobody used trailers, and because RFC 2616
    // says you SHOULD (but not must) predeclare any trailers in the
    // header, the official ResponseWriter rules said trailers in Go must
    // be predeclared, and then we reuse the same ResponseWriter.Header()
    // map to mean both Headers and Trailers.  When it's time to write the
    // Trailers, we pick out the fields of Headers that were declared as
    // trailers. That worked for a while, until we found the first major
    // user of Trailers in the wild: gRPC (using them only over http2),
    // and gRPC libraries permit setting trailers mid-stream without
    // predeclarnig them. So: change of plans. We still permit the old
    // way, but we also permit this hack: if a Header() key begins with
    // "Trailer:", the suffix of that key is a Trailer. Because ':' is an
    // invalid token byte anyway, there is no ambiguity. (And it's already
    // filtered out) It's mildly hacky, but not terrible.
    
    The official pre-declaring way still works. Example from net/http docs:
    https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
    And ResponseWriter docs explaining it:
    https://golang.org/pkg/net/http/#ResponseWriter
    
    I don't want to add a new interface-assertable upgrade type (like
    Hijacker or Flusher) for this because it's hurts composability and
    makes everybody in the ecocsystem implement those, and two optional
    interfaces is already bad enough. This is a weird enough feature
    (Trailers by itself is weird enough), that I don't feel like a third
    optional interface is worth it.
    
    This code also filters invalid header fields (updates golang/go#14048),
    since I had to update that code as part of this. But I want to later
    return an error back to the user if possible. Or log something.
    
    With this CL, all the grpc-go end2end tests pass with a new http2-based
    Server implementation:
    https://github.com/bradfitz/grpc-go/commit/a06f8f0593bfa8a0af72e57fb3916144f7b30121
    
    Change-Id: I80f863d05a1810bd6f302f34932ad9df0a6646a6
    Reviewed-on: https://go-review.googlesource.com/19131Reviewed-by: 's avatarAndrew Gerrand <adg@golang.org>
    Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    d513e585
Name
Last commit
Last update
context Loading commit data...
dict Loading commit data...
html Loading commit data...
http2 Loading commit data...
icmp Loading commit data...
idna Loading commit data...
internal Loading commit data...
ipv4 Loading commit data...
ipv6 Loading commit data...
netutil Loading commit data...
proxy Loading commit data...
publicsuffix Loading commit data...
trace Loading commit data...
webdav Loading commit data...
websocket Loading commit data...
xsrftoken Loading commit data...
.gitattributes Loading commit data...
.gitignore Loading commit data...
AUTHORS Loading commit data...
CONTRIBUTING.md Loading commit data...
CONTRIBUTORS Loading commit data...
LICENSE Loading commit data...
PATENTS Loading commit data...
README Loading commit data...
codereview.cfg Loading commit data...