1
0
mirror of https://github.com/golang/go synced 2024-11-18 11:34:45 -07:00

net/http: send an explicit zero Content-Length when Handler never Writes

Fixes #4004

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/6472055
This commit is contained in:
Brad Fitzpatrick 2012-08-26 11:17:55 -07:00
parent 79473d6b1c
commit 49f29c9c22
2 changed files with 42 additions and 2 deletions

View File

@ -1207,6 +1207,38 @@ func TestCaseSensitiveMethod(t *testing.T) {
res.Body.Close() res.Body.Close()
} }
// TestContentLengthZero tests that for both an HTTP/1.0 and HTTP/1.1
// request (both keep-alive), when a Handler never writes any
// response, the net/http package adds a "Content-Length: 0" response
// header.
func TestContentLengthZero(t *testing.T) {
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {}))
defer ts.Close()
for _, version := range []string{"HTTP/1.0", "HTTP/1.1"} {
conn, err := net.Dial("tcp", ts.Listener.Addr().String())
if err != nil {
t.Fatalf("error dialing: %v", err)
}
_, err = fmt.Fprintf(conn, "GET / %v\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n", version)
if err != nil {
t.Fatalf("error writing: %v", err)
}
req, _ := NewRequest("GET", "/", nil)
res, err := ReadResponse(bufio.NewReader(conn), req)
if err != nil {
t.Fatalf("error reading response: %v", err)
}
if te := res.TransferEncoding; len(te) > 0 {
t.Errorf("For version %q, Transfer-Encoding = %q; want none", version, te)
}
if cl := res.ContentLength; cl != 0 {
t.Errorf("For version %q, Content-Length = %v; want 0", version, cl)
}
conn.Close()
}
}
// goTimeout runs f, failing t if f takes more than ns to complete. // goTimeout runs f, failing t if f takes more than ns to complete.
func goTimeout(t *testing.T, d time.Duration, f func()) { func goTimeout(t *testing.T, d time.Duration, f func()) {
ch := make(chan bool, 2) ch := make(chan bool, 2)

View File

@ -512,8 +512,16 @@ func (w *response) Write(data []byte) (n int, err error) {
} }
func (w *response) finishRequest() { func (w *response) finishRequest() {
// If this was an HTTP/1.0 request with keep-alive and we sent a Content-Length // If the handler never wrote any bytes and never sent a Content-Length
// back, we can make this a keep-alive response ... // response header, set the length explicitly to zero. This helps
// HTTP/1.0 clients keep their "keep-alive" connections alive, and for
// HTTP/1.1 clients is just as good as the alternative: sending a
// chunked response and immediately sending the zero-length EOF chunk.
if w.written == 0 && w.header.get("Content-Length") == "" {
w.header.Set("Content-Length", "0")
}
// If this was an HTTP/1.0 request with keep-alive and we sent a
// Content-Length back, we can make this a keep-alive response ...
if w.req.wantsHttp10KeepAlive() { if w.req.wantsHttp10KeepAlive() {
sentLength := w.header.get("Content-Length") != "" sentLength := w.header.get("Content-Length") != ""
if sentLength && w.header.get("Connection") == "keep-alive" { if sentLength && w.header.get("Connection") == "keep-alive" {