Added Post() method to client

This commit is contained in:
Aliaksandr Valialkin
2015-11-13 16:13:22 +02:00
parent 48fd01e5e0
commit f8bfa12215
2 changed files with 125 additions and 48 deletions
+61 -44
View File
@@ -30,13 +30,17 @@ func Do(req *Request, resp *Response) error {
}
// Get fetches url contents into dst.
//
// Use Do for request customization.
func Get(dst []byte, url string) (statusCode int, body []byte, err error) {
return defaultClient.Get(dst, url)
}
// GetBytes fetches url contents into dst.
func GetBytes(dst, url []byte) (statusCode int, body []byte, err error) {
return defaultClient.GetBytes(dst, url)
// Post sends POST request to the given url with the given POST arguments.
//
// Use Do for request customization.
func Post(dst []byte, url string, postArgs *Args) (statusCode int, body []byte, err error) {
return defaultClient.Post(dst, url, postArgs)
}
var defaultClient Client
@@ -75,37 +79,17 @@ type Client struct {
}
// Get fetches url contents into dst.
//
// Use Do for request customization.
func (c *Client) Get(dst []byte, url string) (statusCode int, body []byte, err error) {
v := urlBufPool.Get()
if v == nil {
v = make([]byte, 1024)
}
buf := v.([]byte)
buf = AppendBytesStr(buf[:0], url)
statusCode, body, err = c.GetBytes(dst, buf)
urlBufPool.Put(v)
return statusCode, body, err
return clientGetURL(dst, url, c)
}
// GetBytes fetches url contents into dst.
func (c *Client) GetBytes(dst, url []byte) (statusCode int, body []byte, err error) {
req := acquireRequest()
req.Header.RequestURI = url
req.ParseURI()
resp := acquireResponse()
resp.Body = dst
if err = c.Do(req, resp); err != nil {
return 0, nil, err
}
statusCode = resp.Header.StatusCode
body = resp.Body
resp.Body = nil
releaseResponse(resp)
req.Header.RequestURI = nil
releaseRequest(req)
return statusCode, body, err
// Post sends POST request to the given url with the given POST arguments.
//
// Use Do for request customization.
func (c *Client) Post(dst []byte, url string, postArgs *Args) (statusCode int, body []byte, err error) {
return clientPostURL(dst, url, postArgs, c)
}
// Do performs the given http request and fills the given http response.
@@ -277,25 +261,55 @@ func (c *HostClient) LastUseTime() time.Time {
}
// Get fetches url contents into dst.
//
// Use Do for request customization.
func (c *HostClient) Get(dst []byte, url string) (statusCode int, body []byte, err error) {
return clientGetURL(dst, url, c)
}
// Post sends POST request to the given url with the given POST arguments.
//
// Use Do for request customization.
func (c *HostClient) Post(dst []byte, url string, postArgs *Args) (statusCode int, body []byte, err error) {
return clientPostURL(dst, url, postArgs, c)
}
type clientDoer interface {
Do(req *Request, resp *Response) error
}
func clientGetURL(dst []byte, url string, c clientDoer) (statusCode int, body []byte, err error) {
req := acquireRequest()
statusCode, body, err = doRequest(req, dst, url, c)
releaseRequest(req)
return statusCode, body, err
}
func clientPostURL(dst []byte, url string, postArgs *Args, c clientDoer) (statusCode int, body []byte, err error) {
req := acquireRequest()
req.Header.Method = strPost
req.Header.contentType = strPostArgsContentType
req.Body = postArgs.AppendBytes(req.Body[:0])
statusCode, body, err = doRequest(req, dst, url, c)
req.Header.Method = nil
req.Header.contentType = nil
// there is no need in req.Body = nil, since Body belongs to req.
releaseRequest(req)
return statusCode, body, err
}
func doRequest(req *Request, dst []byte, url string, c clientDoer) (statusCode int, body []byte, err error) {
v := urlBufPool.Get()
if v == nil {
v = make([]byte, 1024)
}
buf := v.([]byte)
buf = AppendBytesStr(buf[:0], url)
statusCode, body, err = c.GetBytes(dst, buf)
urlBufPool.Put(v)
return statusCode, body, err
}
var urlBufPool sync.Pool
// GetBytes fetches url contents into dst.
func (c *HostClient) GetBytes(dst, url []byte) (statusCode int, body []byte, err error) {
req := acquireRequest()
req.Header.RequestURI = url
req.ParseURI()
req.Header.RequestURI = buf
resp := acquireResponse()
resp.Body = dst
@@ -308,11 +322,14 @@ func (c *HostClient) GetBytes(dst, url []byte) (statusCode int, body []byte, err
releaseResponse(resp)
req.Header.RequestURI = nil
releaseRequest(req)
urlBufPool.Put(v)
return statusCode, body, err
}
var (
urlBufPool sync.Pool
requestPool sync.Pool
responsePool sync.Pool
)
+64 -4
View File
@@ -30,6 +30,7 @@ func TestClientHTTPSConcurrent(t *testing.T) {
go func() {
defer wg.Done()
testClientGet(t, &defaultClient, addr, 3000)
testClientPost(t, &defaultClient, addr, 1000)
}()
}
wg.Wait()
@@ -51,6 +52,7 @@ func TestClientManyServers(t *testing.T) {
go func() {
defer wg.Done()
testClientGet(t, &defaultClient, addr, 3000)
testClientPost(t, &defaultClient, addr, 1000)
}()
}
wg.Wait()
@@ -65,7 +67,16 @@ func TestClientGet(t *testing.T) {
testClientGet(t, &defaultClient, addr, 100)
}
func TestClientGetConcurrent(t *testing.T) {
func TestClientPost(t *testing.T) {
addr := "127.0.0.1:56798"
s := startEchoServer(t, "tcp", addr)
defer s.Stop()
addr = "http://" + addr
testClientPost(t, &defaultClient, addr, 100)
}
func TestClientConcurrent(t *testing.T) {
addr := "127.0.0.1:56780"
s := startEchoServer(t, "tcp", addr)
defer s.Stop()
@@ -77,6 +88,7 @@ func TestClientGetConcurrent(t *testing.T) {
go func() {
defer wg.Done()
testClientGet(t, &defaultClient, addr, 3000)
testClientPost(t, &defaultClient, addr, 1000)
}()
}
wg.Wait()
@@ -91,8 +103,17 @@ func TestHostClientGet(t *testing.T) {
testHostClientGet(t, c, 100)
}
func TestHostClientGetConcurrent(t *testing.T) {
addr := "./TestHostClientGetConcurrent.unix"
func TestHostClientPost(t *testing.T) {
addr := "./TestHostClientPost.unix"
s := startEchoServer(t, "unix", addr)
defer s.Stop()
c := createEchoClient(t, "unix", addr)
testHostClientPost(t, c, 100)
}
func TestHostClientConcurrent(t *testing.T) {
addr := "./TestHostClientConcurrent.unix"
s := startEchoServer(t, "unix", addr)
defer s.Stop()
c := createEchoClient(t, "unix", addr)
@@ -103,6 +124,7 @@ func TestHostClientGetConcurrent(t *testing.T) {
go func() {
defer wg.Done()
testHostClientGet(t, c, 3000)
testHostClientPost(t, c, 1000)
}()
}
wg.Wait()
@@ -130,10 +152,41 @@ func testClientGet(t *testing.T, c clientGetter, addr string, n int) {
}
}
func testClientPost(t *testing.T, c clientPoster, addr string, n int) {
var buf []byte
var args Args
for i := 0; i < n; i++ {
uri := fmt.Sprintf("%s/foo/%d?bar=baz", addr, i)
args.Set("xx", fmt.Sprintf("yy%d", i))
args.Set("zzz", fmt.Sprintf("qwe_%d", i))
argsS := args.String()
statusCode, body, err := c.Post(buf, uri, &args)
buf = body
if err != nil {
t.Fatalf("unexpected error when doing http request: %s", err)
}
if statusCode != StatusOK {
t.Fatalf("unexpected status code: %d. Expecting %d", statusCode, StatusOK)
}
s := string(body)
if s != argsS {
t.Fatalf("unexpected response %q. Expecting %q", s, argsS)
}
}
}
func testHostClientGet(t *testing.T, c *HostClient, n int) {
testClientGet(t, c, "http://google.com", n)
}
func testHostClientPost(t *testing.T, c *HostClient, n int) {
testClientPost(t, c, "http://post-host.com", n)
}
type clientPoster interface {
Post(dst []byte, uri string, postArgs *Args) (int, []byte, error)
}
type clientGetter interface {
Get(dst []byte, uri string) (int, []byte, error)
}
@@ -198,7 +251,14 @@ func startEchoServerExt(t *testing.T, network, addr string, isTLS bool) *testEch
s := &Server{
Handler: func(ctx *RequestCtx) {
ctx.Request.ParseURI()
ctx.Success("text/plain", ctx.Request.URI.URI)
if ctx.IsGet() {
ctx.Success("text/plain", ctx.Request.URI.URI)
} else if ctx.IsPost() {
if err := ctx.Request.ParsePostArgs(); err != nil {
t.Fatalf("cannot parse post arguments: %s", err)
}
ctx.SetResponseBody(ctx.Request.Body)
}
},
}
ch := make(chan struct{})