mirror of
https://github.com/golang/go
synced 2024-11-22 01:24:42 -07:00
http: fix handling of Close, use Close in http.Post
default to HTTP/1.1 R=petar-m CC=golang-dev https://golang.org/cl/224041
This commit is contained in:
parent
1be05bbe1e
commit
37666561b2
@ -139,6 +139,7 @@ func Post(url string, bodyType string, body io.Reader) (r *Response, err os.Erro
|
|||||||
req.Method = "POST"
|
req.Method = "POST"
|
||||||
req.ProtoMajor = 1
|
req.ProtoMajor = 1
|
||||||
req.ProtoMinor = 1
|
req.ProtoMinor = 1
|
||||||
|
req.Close = true
|
||||||
req.Body = nopCloser{body}
|
req.Body = nopCloser{body}
|
||||||
req.Header = map[string]string{
|
req.Header = map[string]string{
|
||||||
"Content-Type": bodyType,
|
"Content-Type": bodyType,
|
||||||
|
@ -82,6 +82,43 @@ var reqWriteTests = []reqWriteTest{
|
|||||||
"Transfer-Encoding: chunked\r\n\r\n" +
|
"Transfer-Encoding: chunked\r\n\r\n" +
|
||||||
"6\r\nabcdef\r\n0\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) {
|
func TestRequestWrite(t *testing.T) {
|
||||||
|
@ -188,10 +188,14 @@ func (resp *Response) Write(w io.Writer) os.Error {
|
|||||||
resp.RequestMethod = strings.ToUpper(resp.RequestMethod)
|
resp.RequestMethod = strings.ToUpper(resp.RequestMethod)
|
||||||
|
|
||||||
// Status line
|
// Status line
|
||||||
text, ok := statusText[resp.StatusCode]
|
text := resp.Status
|
||||||
|
if text == "" {
|
||||||
|
var ok bool
|
||||||
|
text, ok = statusText[resp.StatusCode]
|
||||||
if !ok {
|
if !ok {
|
||||||
text = "status code " + strconv.Itoa(resp.StatusCode)
|
text = "status code " + strconv.Itoa(resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
io.WriteString(w, "HTTP/"+strconv.Itoa(resp.ProtoMajor)+".")
|
io.WriteString(w, "HTTP/"+strconv.Itoa(resp.ProtoMajor)+".")
|
||||||
io.WriteString(w, strconv.Itoa(resp.ProtoMinor)+" ")
|
io.WriteString(w, strconv.Itoa(resp.ProtoMinor)+" ")
|
||||||
io.WriteString(w, strconv.Itoa(resp.StatusCode)+" "+text+"\r\n")
|
io.WriteString(w, strconv.Itoa(resp.StatusCode)+" "+text+"\r\n")
|
||||||
|
@ -42,10 +42,11 @@ var respWriteTests = []respWriteTest{
|
|||||||
Body: nopCloser{bytes.NewBufferString("abcdef")},
|
Body: nopCloser{bytes.NewBufferString("abcdef")},
|
||||||
ContentLength: 6,
|
ContentLength: 6,
|
||||||
TransferEncoding: []string{"chunked"},
|
TransferEncoding: []string{"chunked"},
|
||||||
Close: true, // TODO(petar): "Connection: close" is not written
|
Close: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"HTTP/1.1 200 OK\r\n" +
|
"HTTP/1.1 200 OK\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
"Transfer-Encoding: chunked\r\n\r\n" +
|
"Transfer-Encoding: chunked\r\n\r\n" +
|
||||||
"6\r\nabcdef\r\n0\r\n\r\n",
|
"6\r\nabcdef\r\n0\r\n\r\n",
|
||||||
},
|
},
|
||||||
|
@ -79,20 +79,28 @@ func noBodyExpected(requestMethod string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *transferWriter) WriteHeader(w io.Writer) (err os.Error) {
|
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
|
// 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 chunked(t.TransferEncoding) {
|
||||||
_, err = io.WriteString(w, "Transfer-Encoding: chunked\r\n")
|
_, 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 {
|
if err != nil {
|
||||||
return
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Write Trailer header
|
// Write Trailer header
|
||||||
if t.Trailer != nil {
|
if t.Trailer != nil {
|
||||||
@ -184,6 +192,11 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) {
|
|||||||
t.RequestMethod = "GET"
|
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
|
// Transfer encoding, content length
|
||||||
t.TransferEncoding, err = fixTransferEncoding(t.Header)
|
t.TransferEncoding, err = fixTransferEncoding(t.Header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -347,6 +360,7 @@ func shouldClose(major, minor int, header map[string]string) bool {
|
|||||||
// TODO: Should split on commas, toss surrounding white space,
|
// TODO: Should split on commas, toss surrounding white space,
|
||||||
// and check each field.
|
// and check each field.
|
||||||
if v == "close" {
|
if v == "close" {
|
||||||
|
header["Connection"] = "", false
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user