req.Method = "POST"
req.ProtoMajor = 1
req.ProtoMinor = 1
+ req.Close = true
req.Body = nopCloser{body}
req.Header = map[string]string{
"Content-Type": bodyType,
"Transfer-Encoding: chunked\r\n\r\n" +
"6\r\nabcdef\r\n0\r\n\r\n",
},
+ // HTTP/1.1 POST => chunked coding; body; empty trailer
+ reqWriteTest{
+ Request{
+ Method: "POST",
+ URL: &URL{
+ Scheme: "http",
+ Host: "www.google.com",
+ Path: "/search",
+ },
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ Header: map[string]string{},
+ Close: true,
+ Body: nopCloser{bytes.NewBufferString("abcdef")},
+ TransferEncoding: []string{"chunked"},
+ },
+
+ "POST /search HTTP/1.1\r\n" +
+ "Host: www.google.com\r\n" +
+ "User-Agent: Go http package\r\n" +
+ "Connection: close\r\n" +
+ "Transfer-Encoding: chunked\r\n\r\n" +
+ "6\r\nabcdef\r\n0\r\n\r\n",
+ },
+ // default to HTTP/1.1
+ reqWriteTest{
+ Request{
+ Method: "GET",
+ RawURL: "/search",
+ Host: "www.google.com",
+ },
+
+ "GET /search HTTP/1.1\r\n" +
+ "Host: www.google.com\r\n" +
+ "User-Agent: Go http package\r\n" +
+ "\r\n",
+ },
}
func TestRequestWrite(t *testing.T) {
resp.RequestMethod = strings.ToUpper(resp.RequestMethod)
// Status line
- text, ok := statusText[resp.StatusCode]
- if !ok {
- text = "status code " + strconv.Itoa(resp.StatusCode)
+ text := resp.Status
+ if text == "" {
+ var ok bool
+ text, ok = statusText[resp.StatusCode]
+ if !ok {
+ text = "status code " + strconv.Itoa(resp.StatusCode)
+ }
}
io.WriteString(w, "HTTP/"+strconv.Itoa(resp.ProtoMajor)+".")
io.WriteString(w, strconv.Itoa(resp.ProtoMinor)+" ")
Body: nopCloser{bytes.NewBufferString("abcdef")},
ContentLength: 6,
TransferEncoding: []string{"chunked"},
- Close: true, // TODO(petar): "Connection: close" is not written
+ Close: true,
},
"HTTP/1.1 200 OK\r\n" +
+ "Connection: close\r\n" +
"Transfer-Encoding: chunked\r\n\r\n" +
"6\r\nabcdef\r\n0\r\n\r\n",
},
}
func (t *transferWriter) WriteHeader(w io.Writer) (err os.Error) {
+ if t.Close {
+ _, err = io.WriteString(w, "Connection: close\r\n")
+ if err != nil {
+ return
+ }
+ }
+
// 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")
- } else {
- if t.ContentLength > 0 || t.ResponseToHEAD {
- 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 {
+ io.WriteString(w, "Content-Length: ")
+ _, err = io.WriteString(w, strconv.Itoa64(t.ContentLength)+"\r\n")
+ if err != nil {
+ return
}
- }
- if err != nil {
- return
}
// Write Trailer header
t.RequestMethod = "GET"
}
+ // Default to HTTP/1.1
+ if t.ProtoMajor == 0 && t.ProtoMinor == 0 {
+ t.ProtoMajor, t.ProtoMinor = 1, 1
+ }
+
// Transfer encoding, content length
t.TransferEncoding, err = fixTransferEncoding(t.Header)
if err != nil {
// TODO: Should split on commas, toss surrounding white space,
// and check each field.
if v == "close" {
+ header["Connection"] = "", false
return true
}
}