Skip to content

Commit

Permalink
Add an option to support GET method with request body (#82)
Browse files Browse the repository at this point in the history
  • Loading branch information
zhiyanliu authored and jeevatkm committed Jul 7, 2017
1 parent 52992d9 commit 3b0e1a8
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 21 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Go Resty first released on Sep 15, 2015 then go-resty grew gradually as a very h
* Cookies for your request and CookieJar support
* SRV Record based request instead of Host URL
* Client settings like `Timeout`, `RedirectPolicy`, `Proxy`, `TLSClientConfig`, `Transport`, etc.
* Optionally allows GET request with payload, see [SetAllowGetMethodPayload](https://godoc.org/github.com/go-resty/resty#Client.SetOutputDirectory#Client.SetAllowGetMethodPayload)
* resty design
* Have client level settings & options and also override at Request level if you want to
* Request and Response middlewares
Expand Down Expand Up @@ -511,6 +512,12 @@ resty.SetRESTMode()
resty.SetHTTPMode()
```

#### Allow GET request with Payload
```go
// Allow GET request with Payload. This is disabled by default.
resty.SetAllowGetMethodPayload(true)
```

#### Wanna Multiple Clients
```go
// Here you go!
Expand Down
44 changes: 27 additions & 17 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,22 @@ var (
// Client type is used for HTTP/RESTful global values
// for all request raised from the client
type Client struct {
HostURL string
QueryParam url.Values
FormData url.Values
Header http.Header
UserInfo *User
Token string
Cookies []*http.Cookie
Error reflect.Type
Debug bool
DisableWarn bool
Log *log.Logger
RetryCount int
RetryWaitTime time.Duration
RetryMaxWaitTime time.Duration
RetryConditions []RetryConditionFunc
HostURL string
QueryParam url.Values
FormData url.Values
Header http.Header
UserInfo *User
Token string
Cookies []*http.Cookie
Error reflect.Type
Debug bool
DisableWarn bool
AllowGetMethodPayload bool
Log *log.Logger
RetryCount int
RetryWaitTime time.Duration
RetryMaxWaitTime time.Duration
RetryConditions []RetryConditionFunc

httpClient *http.Client
transport *http.Transport
Expand Down Expand Up @@ -373,6 +374,15 @@ func (c *Client) SetDisableWarn(d bool) *Client {
return c
}

// SetAllowGetMethodPayload method allows the GET method with payload on `go-resty` client.
// For example: go-resty allows the user sends request with a payload on HTTP GET method.
// resty.SetAllowGetMethodPayload(true)
//
func (c *Client) SetAllowGetMethodPayload(a bool) *Client {
c.AllowGetMethodPayload = a
return c
}

// SetLogger method sets given writer for logging go-resty request and response details.
// Default is os.Stderr
// file, _ := os.OpenFile("/Users/jeeva/go-resty.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
Expand Down Expand Up @@ -851,8 +861,8 @@ func getPointer(v interface{}) interface{} {
return reflect.New(vv.Type()).Interface()
}

func isPayloadSupported(m string) bool {
return (m == MethodPost || m == MethodPut || m == MethodDelete || m == MethodPatch)
func isPayloadSupported(m string, allowMethodGet bool) bool {
return (m == MethodPost || m == MethodPut || m == MethodDelete || m == MethodPatch || (allowMethodGet && m == MethodGet))
}

func typeOf(i interface{}) reflect.Type {
Expand Down
21 changes: 20 additions & 1 deletion client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ func TestClientOptions(t *testing.T) {

SetRetryCount(3)
assertEqual(t, 3, DefaultClient.RetryCount)

rwt := time.Duration(1000) * time.Millisecond
SetRetryWaitTime(rwt)
assertEqual(t, rwt, DefaultClient.RetryWaitTime)
Expand Down Expand Up @@ -324,6 +324,9 @@ func TestClientOptions(t *testing.T) {
SetDebug(true)
assertEqual(t, DefaultClient.Debug, true)

SetAllowGetMethodPayload(true)
assertEqual(t, DefaultClient.AllowGetMethodPayload, true)

SetScheme("http")
assertEqual(t, DefaultClient.scheme, "http")

Expand All @@ -344,3 +347,19 @@ func TestClientPreRequestHook(t *testing.T) {
return nil
})
}

func TestClientAllowsGetMethodPayload(t *testing.T) {
ts := createGetServer(t)
defer ts.Close()

c := dc()
c.SetAllowGetMethodPayload(true)
c.SetPreRequestHook(func(*Client, *Request) error { return nil }) // for coverage

payload := "test-payload"
resp, err := c.R().SetBody(payload).Get(ts.URL + "/get-method-payload-test")

assertError(t, err)
assertEqual(t, http.StatusOK, resp.StatusCode())
assertEqual(t, payload, resp.String())
}
5 changes: 5 additions & 0 deletions default.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,11 @@ func SetDebug(d bool) *Client {
return DefaultClient.SetDebug(d)
}

// SetAllowGetMethodPayload method allows the GET method with payload. See `Client.SetAllowGetMethodPayload` for more information.
func SetAllowGetMethodPayload(a bool) *Client {
return DefaultClient.SetAllowGetMethodPayload(a)
}

// SetRetryCount method sets the retry count. See `Client.SetRetryCount` for more information.
func SetRetryCount(count int) *Client {
return DefaultClient.SetRetryCount(count)
Expand Down
3 changes: 1 addition & 2 deletions middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ func parseRequestHeader(c *Client, r *Request) error {
}

func parseRequestBody(c *Client, r *Request) (err error) {
if isPayloadSupported(r.Method) {

if isPayloadSupported(r.Method, c.AllowGetMethodPayload) {
// Handling Multipart
if r.isMultiPart && !(r.Method == MethodPatch) {
if err = handleMultipart(c, r); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion request.go
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ func (r *Request) Execute(method, url string) (*Response, error) {

func (r *Request) fmtBodyString() (body string) {
body = "***** NO CONTENT *****"
if isPayloadSupported(r.Method) {
if isPayloadSupported(r.Method, r.client.AllowGetMethodPayload) {
// multipart or form-data
if r.isMultiPart || r.isFormData {
body = string(r.bodyBuf.Bytes())
Expand Down
6 changes: 6 additions & 0 deletions resty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,12 @@ func createGetServer(t *testing.T) *httptest.Server {
w.Header().Set("Content-Type", "image/png")
w.Header().Set("Content-Length", strconv.Itoa(len(fileBytes)))
_, _ = w.Write(fileBytes)
} else if r.URL.Path == "/get-method-payload-test" {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Errorf("Error: could not read get body: %s", err.Error())
}
_, _ = w.Write(body)
}
}
})
Expand Down

0 comments on commit 3b0e1a8

Please sign in to comment.