mirror of
https://github.com/golang/go
synced 2024-11-21 15:04:44 -07:00
http: always include Content-Length header, even for 0
fixes #2221 R=golang-dev, bradfitz CC=golang-dev https://golang.org/cl/4952052
This commit is contained in:
parent
ab596cae9e
commit
80700eb817
@ -246,14 +246,19 @@ var reqWriteTests = []reqWriteTest{
|
||||
|
||||
Body: func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 0)) },
|
||||
|
||||
// RFC 2616 Section 14.13 says Content-Length should be specified
|
||||
// unless body is prohibited by the request method.
|
||||
// Also, nginx expects it for POST and PUT.
|
||||
WantWrite: "POST / HTTP/1.1\r\n" +
|
||||
"Host: example.com\r\n" +
|
||||
"User-Agent: Go http package\r\n" +
|
||||
"Content-Length: 0\r\n" +
|
||||
"\r\n",
|
||||
|
||||
WantProxy: "POST / HTTP/1.1\r\n" +
|
||||
"Host: example.com\r\n" +
|
||||
"User-Agent: Go http package\r\n" +
|
||||
"Content-Length: 0\r\n" +
|
||||
"\r\n",
|
||||
},
|
||||
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
// sanitizes them without changing the user object and provides methods for
|
||||
// writing the respective header, body and trailer in wire format.
|
||||
type transferWriter struct {
|
||||
Method string
|
||||
Body io.Reader
|
||||
BodyCloser io.Closer
|
||||
ResponseToHEAD bool
|
||||
@ -38,7 +39,7 @@ func newTransferWriter(r interface{}) (t *transferWriter, err os.Error) {
|
||||
if rr.ContentLength != 0 && rr.Body == nil {
|
||||
return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", rr.ContentLength)
|
||||
}
|
||||
|
||||
t.Method = rr.Method
|
||||
t.Body = rr.Body
|
||||
t.BodyCloser = rr.Body
|
||||
t.ContentLength = rr.ContentLength
|
||||
@ -69,6 +70,7 @@ func newTransferWriter(r interface{}) (t *transferWriter, err os.Error) {
|
||||
}
|
||||
}
|
||||
case *Response:
|
||||
t.Method = rr.Request.Method
|
||||
t.Body = rr.Body
|
||||
t.BodyCloser = rr.Body
|
||||
t.ContentLength = rr.ContentLength
|
||||
@ -110,6 +112,27 @@ func noBodyExpected(requestMethod string) bool {
|
||||
return requestMethod == "HEAD"
|
||||
}
|
||||
|
||||
func (t *transferWriter) shouldSendContentLength() bool {
|
||||
if chunked(t.TransferEncoding) {
|
||||
return false
|
||||
}
|
||||
if t.ContentLength > 0 {
|
||||
return true
|
||||
}
|
||||
if t.ResponseToHEAD {
|
||||
return true
|
||||
}
|
||||
// Many servers expect a Content-Length for these methods
|
||||
if t.Method == "POST" || t.Method == "PUT" {
|
||||
return true
|
||||
}
|
||||
if t.ContentLength == 0 && isIdentity(t.TransferEncoding) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *transferWriter) WriteHeader(w io.Writer) (err os.Error) {
|
||||
if t.Close {
|
||||
_, err = io.WriteString(w, "Connection: close\r\n")
|
||||
@ -121,14 +144,14 @@ func (t *transferWriter) WriteHeader(w io.Writer) (err os.Error) {
|
||||
// Write Content-Length and/or Transfer-Encoding whose values are a
|
||||
// function of the sanitized field triple (Body, ContentLength,
|
||||
// TransferEncoding)
|
||||
if chunked(t.TransferEncoding) {
|
||||
_, err = io.WriteString(w, "Transfer-Encoding: chunked\r\n")
|
||||
if t.shouldSendContentLength() {
|
||||
io.WriteString(w, "Content-Length: ")
|
||||
_, err = io.WriteString(w, strconv.Itoa64(t.ContentLength)+"\r\n")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else if t.ContentLength > 0 || t.ResponseToHEAD || (t.ContentLength == 0 && isIdentity(t.TransferEncoding)) {
|
||||
io.WriteString(w, "Content-Length: ")
|
||||
_, err = io.WriteString(w, strconv.Itoa64(t.ContentLength)+"\r\n")
|
||||
} else if chunked(t.TransferEncoding) {
|
||||
_, err = io.WriteString(w, "Transfer-Encoding: chunked\r\n")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user