mirror of
https://github.com/golang/go
synced 2024-11-25 06:07:58 -07:00
http: add NewRequest helper
NewRequest will save a lot of boilerplate code. This also updates some docs on Request.Write and adds some tests. R=rsc, petar-m, r CC=golang-dev https://golang.org/cl/4406047
This commit is contained in:
parent
89fc2c8f4f
commit
71f9dc2cea
@ -199,10 +199,14 @@ const defaultUserAgent = "Go http package"
|
|||||||
// UserAgent (defaults to defaultUserAgent)
|
// UserAgent (defaults to defaultUserAgent)
|
||||||
// Referer
|
// Referer
|
||||||
// Header
|
// Header
|
||||||
|
// Cookie
|
||||||
|
// ContentLength
|
||||||
|
// TransferEncoding
|
||||||
// Body
|
// Body
|
||||||
//
|
//
|
||||||
// If Body is present, Write forces "Transfer-Encoding: chunked" as a header
|
// If Body is present but Content-Length is <= 0, Write adds
|
||||||
// and then closes Body when finished sending it.
|
// "Transfer-Encoding: chunked" to the header. Body is closed after
|
||||||
|
// it is sent.
|
||||||
func (req *Request) Write(w io.Writer) os.Error {
|
func (req *Request) Write(w io.Writer) os.Error {
|
||||||
return req.write(w, false)
|
return req.write(w, false)
|
||||||
}
|
}
|
||||||
@ -420,6 +424,29 @@ func (cr *chunkedReader) Read(b []uint8) (n int, err os.Error) {
|
|||||||
return n, cr.err
|
return n, cr.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewRequest returns a new Request given a method, URL, and optional body.
|
||||||
|
func NewRequest(method, url string, body io.Reader) (*Request, os.Error) {
|
||||||
|
u, err := ParseURL(url)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rc, ok := body.(io.ReadCloser)
|
||||||
|
if !ok && body != nil {
|
||||||
|
rc = ioutil.NopCloser(body)
|
||||||
|
}
|
||||||
|
req := &Request{
|
||||||
|
Method: method,
|
||||||
|
URL: u,
|
||||||
|
Proto: "HTTP/1.1",
|
||||||
|
ProtoMajor: 1,
|
||||||
|
ProtoMinor: 1,
|
||||||
|
Header: make(Header),
|
||||||
|
Body: rc,
|
||||||
|
Host: u.Host,
|
||||||
|
}
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ReadRequest reads and parses a request from b.
|
// ReadRequest reads and parses a request from b.
|
||||||
func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) {
|
func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) {
|
||||||
|
|
||||||
|
@ -6,7 +6,10 @@ package http
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -133,6 +136,41 @@ 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 with Content-Length, no chunking
|
||||||
|
{
|
||||||
|
Request{
|
||||||
|
Method: "POST",
|
||||||
|
URL: &URL{
|
||||||
|
Scheme: "http",
|
||||||
|
Host: "www.google.com",
|
||||||
|
Path: "/search",
|
||||||
|
},
|
||||||
|
ProtoMajor: 1,
|
||||||
|
ProtoMinor: 1,
|
||||||
|
Header: Header{},
|
||||||
|
Close: true,
|
||||||
|
ContentLength: 6,
|
||||||
|
},
|
||||||
|
|
||||||
|
[]byte("abcdef"),
|
||||||
|
|
||||||
|
"POST /search HTTP/1.1\r\n" +
|
||||||
|
"Host: www.google.com\r\n" +
|
||||||
|
"User-Agent: Go http package\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"Content-Length: 6\r\n" +
|
||||||
|
"\r\n" +
|
||||||
|
"abcdef",
|
||||||
|
|
||||||
|
"POST http://www.google.com/search HTTP/1.1\r\n" +
|
||||||
|
"User-Agent: Go http package\r\n" +
|
||||||
|
"Connection: close\r\n" +
|
||||||
|
"Content-Length: 6\r\n" +
|
||||||
|
"\r\n" +
|
||||||
|
"abcdef",
|
||||||
|
},
|
||||||
|
|
||||||
// default to HTTP/1.1
|
// default to HTTP/1.1
|
||||||
{
|
{
|
||||||
Request{
|
Request{
|
||||||
@ -189,3 +227,26 @@ func TestRequestWrite(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type closeChecker struct {
|
||||||
|
io.Reader
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *closeChecker) Close() os.Error {
|
||||||
|
rc.closed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestRequestWriteClosesBody tests that Request.Write does close its request.Body.
|
||||||
|
// It also indirectly tests NewRequest and that it doesn't wrap an existing Closer
|
||||||
|
// inside a NopCloser.
|
||||||
|
func TestRequestWriteClosesBody(t *testing.T) {
|
||||||
|
rc := &closeChecker{Reader: strings.NewReader("my body")}
|
||||||
|
req, _ := NewRequest("GET", "http://foo.com/", rc)
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
req.Write(buf)
|
||||||
|
if !rc.closed {
|
||||||
|
t.Error("body not closed after write")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user