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",
},
// 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
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
}
}
case *Response:
+ t.Method = rr.Request.Method
t.Body = rr.Body
t.BodyCloser = rr.Body
t.ContentLength = rr.ContentLength
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")
// 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
}