ioutil: add NopCloser

R=rsc, dsymonds
CC=golang-dev
https://golang.org/cl/4278044
diff --git a/src/pkg/archive/zip/reader.go b/src/pkg/archive/zip/reader.go
index d8d9bba..3b265c9 100644
--- a/src/pkg/archive/zip/reader.go
+++ b/src/pkg/archive/zip/reader.go
@@ -19,6 +19,7 @@
 	"hash/crc32"
 	"encoding/binary"
 	"io"
+	"io/ioutil"
 	"os"
 )
 
@@ -109,7 +110,7 @@
 	r := io.NewSectionReader(f.zipr, off+f.bodyOffset, size)
 	switch f.Method {
 	case 0: // store (no compression)
-		rc = nopCloser{r}
+		rc = ioutil.NopCloser(r)
 	case 8: // DEFLATE
 		rc = flate.NewReader(r)
 	default:
@@ -147,12 +148,6 @@
 
 func (r *checksumReader) Close() os.Error { return r.rc.Close() }
 
-type nopCloser struct {
-	io.Reader
-}
-
-func (f nopCloser) Close() os.Error { return nil }
-
 func readFileHeader(f *File, r io.Reader) (err os.Error) {
 	defer func() {
 		if rerr, ok := recover().(os.Error); ok {
diff --git a/src/pkg/http/cgi/child.go b/src/pkg/http/cgi/child.go
index e410c0a..c7d48b9 100644
--- a/src/pkg/http/cgi/child.go
+++ b/src/pkg/http/cgi/child.go
@@ -12,6 +12,7 @@
 	"fmt"
 	"http"
 	"io"
+	"io/ioutil"
 	"os"
 	"strconv"
 	"strings"
@@ -67,7 +68,7 @@
 			return nil, os.NewError("cgi: bad CONTENT_LENGTH in environment: " + lenstr)
 		}
 		r.ContentLength = clen
-		r.Body = nopCloser{io.LimitReader(os.Stdin, clen)}
+		r.Body = ioutil.NopCloser(io.LimitReader(os.Stdin, clen))
 	}
 
 	// Copy "HTTP_FOO_BAR" variables to "Foo-Bar" Headers
@@ -103,13 +104,6 @@
 	return r, nil
 }
 
-// TODO: move this to ioutil or something.  It's copy/pasted way too often.
-type nopCloser struct {
-	io.Reader
-}
-
-func (nopCloser) Close() os.Error { return nil }
-
 // Serve executes the provided Handler on the currently active CGI
 // request, if any. If there's no current CGI environment
 // an error is returned. The provided handler may be nil to use
diff --git a/src/pkg/http/client.go b/src/pkg/http/client.go
index c4f7e94..c43e583 100644
--- a/src/pkg/http/client.go
+++ b/src/pkg/http/client.go
@@ -11,6 +11,7 @@
 	"encoding/base64"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"os"
 	"strconv"
 	"strings"
@@ -235,7 +236,7 @@
 	req.ProtoMajor = 1
 	req.ProtoMinor = 1
 	req.Close = true
-	req.Body = nopCloser{body}
+	req.Body = ioutil.NopCloser(body)
 	req.Header = Header{
 		"Content-Type": {bodyType},
 	}
@@ -270,7 +271,7 @@
 	req.ProtoMinor = 1
 	req.Close = true
 	body := urlencode(data)
-	req.Body = nopCloser{body}
+	req.Body = ioutil.NopCloser(body)
 	req.Header = Header{
 		"Content-Type":   {"application/x-www-form-urlencoded"},
 		"Content-Length": {strconv.Itoa(body.Len())},
@@ -310,9 +311,3 @@
 	}
 	return send(&req, c.Transport)
 }
-
-type nopCloser struct {
-	io.Reader
-}
-
-func (nopCloser) Close() os.Error { return nil }
diff --git a/src/pkg/http/dump.go b/src/pkg/http/dump.go
index 73ac979..306c45b 100644
--- a/src/pkg/http/dump.go
+++ b/src/pkg/http/dump.go
@@ -7,10 +7,10 @@
 import (
 	"bytes"
 	"io"
+	"io/ioutil"
 	"os"
 )
 
-
 // One of the copies, say from b to r2, could be avoided by using a more
 // elaborate trick where the other copy is made during Request/Response.Write.
 // This would complicate things too much, given that these functions are for
@@ -23,7 +23,7 @@
 	if err = b.Close(); err != nil {
 		return nil, nil, err
 	}
-	return nopCloser{&buf}, nopCloser{bytes.NewBuffer(buf.Bytes())}, nil
+	return ioutil.NopCloser(&buf), ioutil.NopCloser(bytes.NewBuffer(buf.Bytes())), nil
 }
 
 // DumpRequest returns the wire representation of req,
diff --git a/src/pkg/http/requestwrite_test.go b/src/pkg/http/requestwrite_test.go
index 03a766e..726baa2 100644
--- a/src/pkg/http/requestwrite_test.go
+++ b/src/pkg/http/requestwrite_test.go
@@ -6,6 +6,7 @@
 
 import (
 	"bytes"
+	"io/ioutil"
 	"testing"
 )
 
@@ -158,7 +159,7 @@
 	for i := range reqWriteTests {
 		tt := &reqWriteTests[i]
 		if tt.Body != nil {
-			tt.Req.Body = nopCloser{bytes.NewBuffer(tt.Body)}
+			tt.Req.Body = ioutil.NopCloser(bytes.NewBuffer(tt.Body))
 		}
 		var braw bytes.Buffer
 		err := tt.Req.Write(&braw)
@@ -173,7 +174,7 @@
 		}
 
 		if tt.Body != nil {
-			tt.Req.Body = nopCloser{bytes.NewBuffer(tt.Body)}
+			tt.Req.Body = ioutil.NopCloser(bytes.NewBuffer(tt.Body))
 		}
 		var praw bytes.Buffer
 		err = tt.Req.WriteProxy(&praw)
diff --git a/src/pkg/http/responsewrite_test.go b/src/pkg/http/responsewrite_test.go
index 0ef7f04..de0635d 100644
--- a/src/pkg/http/responsewrite_test.go
+++ b/src/pkg/http/responsewrite_test.go
@@ -6,6 +6,7 @@
 
 import (
 	"bytes"
+	"io/ioutil"
 	"testing"
 )
 
@@ -23,7 +24,7 @@
 			ProtoMinor:    0,
 			RequestMethod: "GET",
 			Header:        Header{},
-			Body:          nopCloser{bytes.NewBufferString("abcdef")},
+			Body:          ioutil.NopCloser(bytes.NewBufferString("abcdef")),
 			ContentLength: 6,
 		},
 
@@ -39,7 +40,7 @@
 			ProtoMinor:    0,
 			RequestMethod: "GET",
 			Header:        Header{},
-			Body:          nopCloser{bytes.NewBufferString("abcdef")},
+			Body:          ioutil.NopCloser(bytes.NewBufferString("abcdef")),
 			ContentLength: -1,
 		},
 		"HTTP/1.0 200 OK\r\n" +
@@ -54,7 +55,7 @@
 			ProtoMinor:       1,
 			RequestMethod:    "GET",
 			Header:           Header{},
-			Body:             nopCloser{bytes.NewBufferString("abcdef")},
+			Body:             ioutil.NopCloser(bytes.NewBufferString("abcdef")),
 			ContentLength:    6,
 			TransferEncoding: []string{"chunked"},
 			Close:            true,
diff --git a/src/pkg/io/ioutil/ioutil.go b/src/pkg/io/ioutil/ioutil.go
index 7e3b44e..ed6c310 100644
--- a/src/pkg/io/ioutil/ioutil.go
+++ b/src/pkg/io/ioutil/ioutil.go
@@ -90,3 +90,15 @@
 	sort.Sort(fi)
 	return fi, nil
 }
+
+type nopCloser struct {
+	io.Reader
+}
+
+func (nopCloser) Close() os.Error { return nil }
+
+// NopCloser returns a ReadCloser with a no-op Close method wrapping
+// the provided Reader r.
+func NopCloser(r io.Reader) io.ReadCloser {
+	return nopCloser{r}
+}