]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: document and test Client.Post treating Reader body as ReadCloser
authorBrad Fitzpatrick <bradfitz@golang.org>
Fri, 19 Jul 2013 02:02:54 +0000 (12:02 +1000)
committerBrad Fitzpatrick <bradfitz@golang.org>
Fri, 19 Jul 2013 02:02:54 +0000 (12:02 +1000)
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/11542044

src/pkg/net/http/client.go
src/pkg/net/http/transport_test.go

index 828422f84c3efa17c1cd0edcacc52c5502321840..331e8ad90e5e4188a4a46a47faed27eaeebbe707 100644 (file)
@@ -74,8 +74,8 @@ type RoundTripper interface {
        // authentication, or cookies.
        //
        // RoundTrip should not modify the request, except for
-       // consuming the Body.  The request's URL and Header fields
-       // are guaranteed to be initialized.
+       // consuming and closing the Body. The request's URL and
+       // Header fields are guaranteed to be initialized.
        RoundTrip(*Request) (*Response, error)
 }
 
@@ -346,6 +346,9 @@ func Post(url string, bodyType string, body io.Reader) (resp *Response, err erro
 // Post issues a POST to the specified URL.
 //
 // Caller should close resp.Body when done reading from it.
+//
+// If the provided body is also an io.Closer, it is closed after the
+// body is successfully written to the server.
 func (c *Client) Post(url string, bodyType string, body io.Reader) (resp *Response, err error) {
        req, err := NewRequest("POST", url, body)
        if err != nil {
index a34760a089914641f8f70d7bc5a7466e71ddbf90..48a8c441f7235e4e20161181dc6329af39262931 100644 (file)
@@ -15,6 +15,7 @@ import (
        "io"
        "io/ioutil"
        "net"
+       "net/http"
        . "net/http"
        "net/http/httptest"
        "net/url"
@@ -1610,6 +1611,42 @@ func TestIdleConnChannelLeak(t *testing.T) {
        }
 }
 
+// Verify the status quo: that the Client.Post function coerces its
+// body into a ReadCloser if it's a Closer, and that the Transport
+// then closes it.
+func TestTransportClosesRequestBody(t *testing.T) {
+       defer afterTest(t)
+       ts := httptest.NewServer(http.HandlerFunc(func(w ResponseWriter, r *Request) {
+               io.Copy(ioutil.Discard, r.Body)
+       }))
+       defer ts.Close()
+
+       tr := &Transport{}
+       defer tr.CloseIdleConnections()
+       cl := &Client{Transport: tr}
+
+       closes := 0
+
+       res, err := cl.Post(ts.URL, "text/plain", countCloseReader{&closes, strings.NewReader("hello")})
+       if err != nil {
+               t.Fatal(err)
+       }
+       res.Body.Close()
+       if closes != 1 {
+               t.Errorf("closes = %d; want 1", closes)
+       }
+}
+
+type countCloseReader struct {
+       n *int
+       io.Reader
+}
+
+func (cr countCloseReader) Close() error {
+       (*cr.n)++
+       return nil
+}
+
 // rgz is a gzip quine that uncompresses to itself.
 var rgz = []byte{
        0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,