Skip to content

Commit

Permalink
http2: fix two cases of Server behavior not matching HTTP/1
Browse files Browse the repository at this point in the history
* don't send automatic Content-Length from Server on HEAD requests if
  response size is 0 (it's possible the handler didn't write because
  they looked at the method)

* don't send Content-Type if handler explicitly set it to nothing.

Matches the behavior of HTTP/1.

Updates golang/go#13532
Updates golang/go#13495

Change-Id: If6e0898095cf88cb14efb6bbe82c88dbc2077e6b
Reviewed-on: https://go-review.googlesource.com/17590
Reviewed-by: Blake Mizerany <[email protected]>
  • Loading branch information
bradfitz committed Dec 9, 2015
1 parent 438097d commit 1796f9b
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 2 deletions.
5 changes: 3 additions & 2 deletions http2/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -1758,10 +1758,11 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
clen = ""
}
}
if clen == "" && rws.handlerDone && bodyAllowedForStatus(rws.status) {
if clen == "" && rws.handlerDone && bodyAllowedForStatus(rws.status) && (len(p) > 0 || !isHeadResp) {
clen = strconv.Itoa(len(p))
}
if rws.snapHeader.Get("Content-Type") == "" && bodyAllowedForStatus(rws.status) {
_, hasContentType := rws.snapHeader["Content-Type"]
if !hasContentType && bodyAllowedForStatus(rws.status) {
ctype = http.DetectContentType(p)
}
var date string
Expand Down
49 changes: 49 additions & 0 deletions http2/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2637,3 +2637,52 @@ func TestServerRejectHeadWithBody(t *testing.T) {
})
st.wantRSTStream(1, ErrCodeProtocol)
}

func TestServerNoAutoContentLengthOnHead(t *testing.T) {
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
// No response body. (or smaller than one frame)
})
defer st.Close()
st.greet()
st.writeHeaders(HeadersFrameParam{
StreamID: 1, // clients send odd numbers
BlockFragment: st.encodeHeader(":method", "HEAD"),
EndStream: true,
EndHeaders: true,
})
h := st.wantHeaders()
headers := decodeHeader(t, h.HeaderBlockFragment())
want := [][2]string{
{":status", "200"},
{"content-type", "text/plain; charset=utf-8"},
}
if !reflect.DeepEqual(headers, want) {
t.Errorf("Headers mismatch.\n got: %q\nwant: %q\n", headers, want)
}
}

// golang.org/issue/13495
func TestServerNoDuplicateContentType(t *testing.T) {
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
w.Header()["Content-Type"] = []string{""}
fmt.Fprintf(w, "<html><head></head><body>hi</body></html>")
})
defer st.Close()
st.greet()
st.writeHeaders(HeadersFrameParam{
StreamID: 1,
BlockFragment: st.encodeHeader(),
EndStream: true,
EndHeaders: true,
})
h := st.wantHeaders()
headers := decodeHeader(t, h.HeaderBlockFragment())
want := [][2]string{
{":status", "200"},
{"content-type", ""},
{"content-length", "41"},
}
if !reflect.DeepEqual(headers, want) {
t.Errorf("Headers mismatch.\n got: %q\nwant: %q\n", headers, want)
}
}

0 comments on commit 1796f9b

Please sign in to comment.