Skip to content

Commit

Permalink
x/net/http2: exclude some header from 1xx responses
Browse files Browse the repository at this point in the history
Content-Length and Transfer-Encoding must not be sent when the response
has no body.

Necessary to fix the tests of golang/go#42597.
  • Loading branch information
dunglas committed May 14, 2022
1 parent 9564170 commit 1f20a3a
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 5 deletions.
1 change: 1 addition & 0 deletions http2/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2681,6 +2681,7 @@ func (rws *responseWriterState) writeHeader(code int) {
streamID: rws.stream.id,
httpResCode: code,
h: h,
noBody: true,
endStream: rws.handlerDone && !rws.hasTrailers(),
}) != nil {
rws.dirty = true
Expand Down
3 changes: 2 additions & 1 deletion http2/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4392,6 +4392,7 @@ func TestServerSendsProcessing(t *testing.T) {
func TestServerSendsEarlyHints(t *testing.T) {
testServerResponse(t, func(w http.ResponseWriter, r *http.Request) error {
h := w.Header()
h.Add("Content-Length", "123")
h.Add("Link", "</style.css>; rel=preload; as=style")
h.Add("Link", "</script.js>; rel=preload; as=script")
w.WriteHeader(http.StatusEarlyHints)
Expand Down Expand Up @@ -4437,7 +4438,7 @@ func TestServerSendsEarlyHints(t *testing.T) {
{"link", "</script.js>; rel=preload; as=script"},
{"link", "</foo.js>; rel=preload; as=script"},
{"content-type", "text/plain; charset=utf-8"},
{"content-length", "5"},
{"content-length", "123"},
}

if !reflect.DeepEqual(goth, wanth) {
Expand Down
19 changes: 15 additions & 4 deletions http2/write.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ type writeResHeaders struct {
httpResCode int // 0 means no ":status" line
h http.Header // may be nil
trailers []string // if non-nil, which keys of h to write. nil means all.
noBody bool // if true, Content-Length and Transfer-Encoding will not be set
endStream bool

date string
Expand Down Expand Up @@ -214,7 +215,12 @@ func (w *writeResHeaders) writeFrame(ctx writeContext) error {
encKV(enc, ":status", httpCodeString(w.httpResCode))
}

encodeHeaders(enc, w.h, w.trailers)
var excludedKeys map[string]bool
if w.noBody {
excludedKeys = map[string]bool{"Content-Length": true, "Transfer-Encoding": true}
}

encodeHeaders(enc, w.h, w.trailers, excludedKeys)

if w.contentType != "" {
encKV(enc, "content-type", w.contentType)
Expand Down Expand Up @@ -273,7 +279,7 @@ func (w *writePushPromise) writeFrame(ctx writeContext) error {
encKV(enc, ":scheme", w.url.Scheme)
encKV(enc, ":authority", w.url.Host)
encKV(enc, ":path", w.url.RequestURI())
encodeHeaders(enc, w.h, nil)
encodeHeaders(enc, w.h, nil, nil)

headerBlock := buf.Bytes()
if len(headerBlock) == 0 {
Expand Down Expand Up @@ -329,8 +335,9 @@ func (wu writeWindowUpdate) writeFrame(ctx writeContext) error {
}

// encodeHeaders encodes an http.Header. If keys is not nil, then (k, h[k])
// is encoded only if k is in keys.
func encodeHeaders(enc *hpack.Encoder, h http.Header, keys []string) {
// is encoded only if k is in keys. If excludeKeys is not nil, then
// (k, k[h]) is encoded only if k is not true in excludeKeys.
func encodeHeaders(enc *hpack.Encoder, h http.Header, keys []string, excludeKeys map[string]bool) {
if keys == nil {
sorter := sorterPool.Get().(*sorter)
// Using defer here, since the returned keys from the
Expand All @@ -340,6 +347,10 @@ func encodeHeaders(enc *hpack.Encoder, h http.Header, keys []string) {
keys = sorter.Keys(h)
}
for _, k := range keys {
if excludeKeys[k] {
continue
}

vv := h[k]
k, ascii := lowerHeader(k)
if !ascii {
Expand Down

0 comments on commit 1f20a3a

Please sign in to comment.