Skip to content

Commit

Permalink
Support Do API style(imroc#137)
Browse files Browse the repository at this point in the history
  • Loading branch information
imroc committed Aug 7, 2022
1 parent 36341da commit ab1e34e
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 10 deletions.
49 changes: 49 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,55 @@ func (c *Client) R() *Request {
}
}

// Get create a new GET request.
func (c *Client) Get() *Request {
r := c.R()
r.Method = http.MethodGet
return r
}

// Post create a new POST request.
func (c *Client) Post() *Request {
r := c.R()
r.Method = http.MethodPost
return r
}

// Patch create a new PATCH request.
func (c *Client) Patch() *Request {
r := c.R()
r.Method = http.MethodPatch
return r
}

// Delete create a new DELETE request.
func (c *Client) Delete() *Request {
r := c.R()
r.Method = http.MethodDelete
return r
}

// Put create a new PUT request.
func (c *Client) Put() *Request {
r := c.R()
r.Method = http.MethodPut
return r
}

// Head create a new HEAD request.
func (c *Client) Head() *Request {
r := c.R()
r.Method = http.MethodHead
return r
}

// Options create a new OPTIONS request.
func (c *Client) Options() *Request {
r := c.R()
r.Method = http.MethodOptions
return r
}

// GetTransport return the underlying transport.
func (c *Client) GetTransport() *Transport {
return c.t
Expand Down
42 changes: 32 additions & 10 deletions request.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ func (r *Request) TraceInfo() TraceInfo {
return ti
}

// SetURL set the url for request.
func (r *Request) SetURL(url string) *Request {
r.RawURL = url
return r
}

// SetFormDataFromValues set the form data from url.Values, will not
// been used if request method does not allow payload.
func (r *Request) SetFormDataFromValues(data urlpkg.Values) *Request {
Expand Down Expand Up @@ -443,21 +449,36 @@ func (r *Request) appendError(err error) {

var errRetryableWithUnReplayableBody = errors.New("retryable request should not have unreplayable body (io.Reader)")

// Send fires http request and return the *Response which is always
// not nil, and the error is not nil if some error happens.
func (r *Request) Send(method, url string) (*Response, error) {
// Do fires http request and return the *Response which is always
// not nil, and the error is not nil if error occurs.
func (r *Request) Do() *Response {
defer func() {
r.responseReturnTime = time.Now()
}()
if r.error != nil {
return &Response{Request: r}, r.error
resp := &Response{Request: r}
resp.Err = r.error
return resp
}
if r.retryOption != nil && r.retryOption.MaxRetries > 0 && r.unReplayableBody != nil { // retryable request should not have unreplayable body
return &Response{Request: r}, errRetryableWithUnReplayableBody
resp := &Response{Request: r}
resp.Err = errRetryableWithUnReplayableBody
return resp
}
resp, err := r.client.do(r)
if err != nil {
resp.Err = err
}
return resp
}

// Send fires http request with specified method and url, returns the
// *Response which is always not nil, and the error is not nil if error occurs.
func (r *Request) Send(method, url string) (*Response, error) {
r.Method = method
r.RawURL = url
return r.client.do(r)
resp := r.Do()
return resp, resp.Err
}

// MustGet like Get, panic if error happens, should only be used to
Expand Down Expand Up @@ -812,10 +833,11 @@ func (r *Request) SetRetryCount(count int) *Request {
// SetRetryInterval sets the custom GetRetryIntervalFunc, you can use this to
// implement your own backoff retry algorithm.
// For example:
// req.SetRetryInterval(func(resp *req.Response, attempt int) time.Duration {
// sleep := 0.01 * math.Exp2(float64(attempt))
// return time.Duration(math.Min(2, sleep)) * time.Second
// })
//
// req.SetRetryInterval(func(resp *req.Response, attempt int) time.Duration {
// sleep := 0.01 * math.Exp2(float64(attempt))
// return time.Duration(math.Min(2, sleep)) * time.Second
// })
func (r *Request) SetRetryInterval(getRetryIntervalFunc GetRetryIntervalFunc) *Request {
r.getRetryOption().GetRetryInterval = getRetryIntervalFunc
return r
Expand Down
10 changes: 10 additions & 0 deletions request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,16 @@ func TestSetBodyMarshal(t *testing.T) {
}
}

func TestDoAPIStyle(t *testing.T) {
c := tc()
user := &UserInfo{}
url := "/search?username=imroc&type=json"

err := c.Get().SetURL(url).Do().Into(user)
tests.AssertEqual(t, true, err == nil)
tests.AssertEqual(t, "imroc", user.Username)
}

func TestSetResult(t *testing.T) {
c := tc()
var user *UserInfo
Expand Down
6 changes: 6 additions & 0 deletions request_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import (
"time"
)

// SetURL is a global wrapper methods which delegated
// to the default client, create a request and SetURL for request.
func SetURL(url string) *Request {
return defaultClient.R().SetURL(url)
}

// SetFormDataFromValues is a global wrapper methods which delegated
// to the default client, create a request and SetFormDataFromValues for request.
func SetFormDataFromValues(data url.Values) *Request {
Expand Down
1 change: 1 addition & 0 deletions request_wrapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func TestGlobalWrapperForRequestSettings(t *testing.T) {
SetPathParam("test", "test"),
SetPathParams(map[string]string{"test": "test"}),
SetFormData(map[string]string{"test": "test"}),
SetURL(""),
SetFormDataFromValues(nil),
SetContentType(header.JsonContentType),
AddRetryCondition(func(rep *Response, err error) bool {
Expand Down
18 changes: 18 additions & 0 deletions response.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ func (r *Response) setReceivedAt() {

// UnmarshalJson unmarshals JSON response body into the specified object.
func (r *Response) UnmarshalJson(v interface{}) error {
if r.Err != nil {
return r.Err
}
b, err := r.ToBytes()
if err != nil {
return err
Expand All @@ -94,6 +97,9 @@ func (r *Response) UnmarshalJson(v interface{}) error {

// UnmarshalXml unmarshals XML response body into the specified object.
func (r *Response) UnmarshalXml(v interface{}) error {
if r.Err != nil {
return r.Err
}
b, err := r.ToBytes()
if err != nil {
return err
Expand All @@ -104,6 +110,9 @@ func (r *Response) UnmarshalXml(v interface{}) error {
// Unmarshal unmarshals response body into the specified object according
// to response `Content-Type`.
func (r *Response) Unmarshal(v interface{}) error {
if r.Err != nil {
return r.Err
}
contentType := r.Header.Get("Content-Type")
if strings.Contains(contentType, "json") {
return r.UnmarshalJson(v)
Expand All @@ -113,6 +122,12 @@ func (r *Response) Unmarshal(v interface{}) error {
return r.UnmarshalJson(v)
}

// Into unmarshals response body into the specified object according
// to response `Content-Type`.
func (r *Response) Into(v interface{}) error {
return r.Unmarshal(v)
}

// Bytes return the response body as []bytes that hava already been read, could be
// nil if not read, the following cases are already read:
// 1. `Request.SetResult` or `Request.SetError` is called.
Expand All @@ -139,6 +154,9 @@ func (r *Response) ToString() (string, error) {

// ToBytes returns the response body as []byte, read body if not have been read.
func (r *Response) ToBytes() ([]byte, error) {
if r.Err != nil {
return nil, r.Err
}
if r.body != nil {
return r.body, nil
}
Expand Down

0 comments on commit ab1e34e

Please sign in to comment.