Skip to content

Commit 1796f9b

Browse files
committed
http2: fix two cases of Server behavior not matching HTTP/1
* 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]>
1 parent 438097d commit 1796f9b

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

http2/server.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,10 +1758,11 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
17581758
clen = ""
17591759
}
17601760
}
1761-
if clen == "" && rws.handlerDone && bodyAllowedForStatus(rws.status) {
1761+
if clen == "" && rws.handlerDone && bodyAllowedForStatus(rws.status) && (len(p) > 0 || !isHeadResp) {
17621762
clen = strconv.Itoa(len(p))
17631763
}
1764-
if rws.snapHeader.Get("Content-Type") == "" && bodyAllowedForStatus(rws.status) {
1764+
_, hasContentType := rws.snapHeader["Content-Type"]
1765+
if !hasContentType && bodyAllowedForStatus(rws.status) {
17651766
ctype = http.DetectContentType(p)
17661767
}
17671768
var date string

http2/server_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2637,3 +2637,52 @@ func TestServerRejectHeadWithBody(t *testing.T) {
26372637
})
26382638
st.wantRSTStream(1, ErrCodeProtocol)
26392639
}
2640+
2641+
func TestServerNoAutoContentLengthOnHead(t *testing.T) {
2642+
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
2643+
// No response body. (or smaller than one frame)
2644+
})
2645+
defer st.Close()
2646+
st.greet()
2647+
st.writeHeaders(HeadersFrameParam{
2648+
StreamID: 1, // clients send odd numbers
2649+
BlockFragment: st.encodeHeader(":method", "HEAD"),
2650+
EndStream: true,
2651+
EndHeaders: true,
2652+
})
2653+
h := st.wantHeaders()
2654+
headers := decodeHeader(t, h.HeaderBlockFragment())
2655+
want := [][2]string{
2656+
{":status", "200"},
2657+
{"content-type", "text/plain; charset=utf-8"},
2658+
}
2659+
if !reflect.DeepEqual(headers, want) {
2660+
t.Errorf("Headers mismatch.\n got: %q\nwant: %q\n", headers, want)
2661+
}
2662+
}
2663+
2664+
// golang.org/issue/13495
2665+
func TestServerNoDuplicateContentType(t *testing.T) {
2666+
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
2667+
w.Header()["Content-Type"] = []string{""}
2668+
fmt.Fprintf(w, "<html><head></head><body>hi</body></html>")
2669+
})
2670+
defer st.Close()
2671+
st.greet()
2672+
st.writeHeaders(HeadersFrameParam{
2673+
StreamID: 1,
2674+
BlockFragment: st.encodeHeader(),
2675+
EndStream: true,
2676+
EndHeaders: true,
2677+
})
2678+
h := st.wantHeaders()
2679+
headers := decodeHeader(t, h.HeaderBlockFragment())
2680+
want := [][2]string{
2681+
{":status", "200"},
2682+
{"content-type", ""},
2683+
{"content-length", "41"},
2684+
}
2685+
if !reflect.DeepEqual(headers, want) {
2686+
t.Errorf("Headers mismatch.\n got: %q\nwant: %q\n", headers, want)
2687+
}
2688+
}

0 commit comments

Comments
 (0)