mirror of
https://github.com/golang/go
synced 2024-11-25 06:07:58 -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)) },
|
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" +
|
WantWrite: "POST / HTTP/1.1\r\n" +
|
||||||
"Host: example.com\r\n" +
|
"Host: example.com\r\n" +
|
||||||
"User-Agent: Go http package\r\n" +
|
"User-Agent: Go http package\r\n" +
|
||||||
|
"Content-Length: 0\r\n" +
|
||||||
"\r\n",
|
"\r\n",
|
||||||
|
|
||||||
WantProxy: "POST / HTTP/1.1\r\n" +
|
WantProxy: "POST / HTTP/1.1\r\n" +
|
||||||
"Host: example.com\r\n" +
|
"Host: example.com\r\n" +
|
||||||
"User-Agent: Go http package\r\n" +
|
"User-Agent: Go http package\r\n" +
|
||||||
|
"Content-Length: 0\r\n" +
|
||||||
"\r\n",
|
"\r\n",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
// sanitizes them without changing the user object and provides methods for
|
// sanitizes them without changing the user object and provides methods for
|
||||||
// writing the respective header, body and trailer in wire format.
|
// writing the respective header, body and trailer in wire format.
|
||||||
type transferWriter struct {
|
type transferWriter struct {
|
||||||
|
Method string
|
||||||
Body io.Reader
|
Body io.Reader
|
||||||
BodyCloser io.Closer
|
BodyCloser io.Closer
|
||||||
ResponseToHEAD bool
|
ResponseToHEAD bool
|
||||||
@ -38,7 +39,7 @@ func newTransferWriter(r interface{}) (t *transferWriter, err os.Error) {
|
|||||||
if rr.ContentLength != 0 && rr.Body == nil {
|
if rr.ContentLength != 0 && rr.Body == nil {
|
||||||
return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", rr.ContentLength)
|
return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", rr.ContentLength)
|
||||||
}
|
}
|
||||||
|
t.Method = rr.Method
|
||||||
t.Body = rr.Body
|
t.Body = rr.Body
|
||||||
t.BodyCloser = rr.Body
|
t.BodyCloser = rr.Body
|
||||||
t.ContentLength = rr.ContentLength
|
t.ContentLength = rr.ContentLength
|
||||||
@ -69,6 +70,7 @@ func newTransferWriter(r interface{}) (t *transferWriter, err os.Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *Response:
|
case *Response:
|
||||||
|
t.Method = rr.Request.Method
|
||||||
t.Body = rr.Body
|
t.Body = rr.Body
|
||||||
t.BodyCloser = rr.Body
|
t.BodyCloser = rr.Body
|
||||||
t.ContentLength = rr.ContentLength
|
t.ContentLength = rr.ContentLength
|
||||||
@ -110,6 +112,27 @@ func noBodyExpected(requestMethod string) bool {
|
|||||||
return requestMethod == "HEAD"
|
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) {
|
func (t *transferWriter) WriteHeader(w io.Writer) (err os.Error) {
|
||||||
if t.Close {
|
if t.Close {
|
||||||
_, err = io.WriteString(w, "Connection: close\r\n")
|
_, 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
|
// Write Content-Length and/or Transfer-Encoding whose values are a
|
||||||
// function of the sanitized field triple (Body, ContentLength,
|
// function of the sanitized field triple (Body, ContentLength,
|
||||||
// TransferEncoding)
|
// TransferEncoding)
|
||||||
if chunked(t.TransferEncoding) {
|
if t.shouldSendContentLength() {
|
||||||
_, err = io.WriteString(w, "Transfer-Encoding: chunked\r\n")
|
io.WriteString(w, "Content-Length: ")
|
||||||
|
_, err = io.WriteString(w, strconv.Itoa64(t.ContentLength)+"\r\n")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else if t.ContentLength > 0 || t.ResponseToHEAD || (t.ContentLength == 0 && isIdentity(t.TransferEncoding)) {
|
} else if chunked(t.TransferEncoding) {
|
||||||
io.WriteString(w, "Content-Length: ")
|
_, err = io.WriteString(w, "Transfer-Encoding: chunked\r\n")
|
||||||
_, err = io.WriteString(w, strconv.Itoa64(t.ContentLength)+"\r\n")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user