Skip to content

Commit 17fa68e

Browse files
committed
Merging implementation of #8 & #11
2 parents f8960ae + c9740e0 commit 17fa68e

File tree

6 files changed

+159
-59
lines changed

6 files changed

+159
-59
lines changed

README.md

+10-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Simple HTTP and REST client for Go inspired by Ruby rest-client. Provides notabl
2020
* Choose between HTTP and RESTful mode. Default is RESTful
2121
* `HTTP` - default upto 10 redirects and no automatic response unmarshal
2222
* `RESTful` - default no redirects and automatic response unmarshal for `JSON` & `XML`
23-
* Client settings like Timeout, RedirectPolicy, Proxy and TLSClientConfig
23+
* Client settings like `Timeout`, `RedirectPolicy`, `Proxy` and `TLSClientConfig`
2424
* Client API design
2525
* Have client level settings & options and also override at Request level if you want to
2626
* [Request](https://godoc.org/github.com/go-resty/resty#Client.OnBeforeRequest) and [Response](https://godoc.org/github.com/go-resty/resty#Client.OnAfterResponse) middleware
@@ -38,7 +38,7 @@ resty tested with Go 1.2 and above.
3838
* FlexibleRedirectPolicy
3939
* DomainCheckRedirectPolicy
4040
* etc. [more info](redirect.go)
41-
* Write Cookies to file from CookiesJar (upcoming)
41+
* Persist Cookies into file in JSON format from resty client (upcoming)
4242
* etc.
4343

4444
## Installation
@@ -104,6 +104,14 @@ resp, err := resty.R().
104104
SetHeader("Accept", "application/json").
105105
SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F").
106106
Get("/search_result")
107+
108+
109+
// Sample of using Request.SetQueryString method
110+
resp, err := resty.R().
111+
SetQueryString("productId=232&template=fresh-sample&cat=resty&source=google&kw=buy a lot more").
112+
SetHeader("Accept", "application/json").
113+
SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F").
114+
Get("/show_product")
107115
```
108116

109117
#### Various POST method combinations

client.go

+43-25
Original file line numberDiff line numberDiff line change
@@ -354,12 +354,7 @@ func (c *Client) SetContentLength(l bool) *Client {
354354
// resty.SetError(Error{})
355355
//
356356
func (c *Client) SetError(err interface{}) *Client {
357-
t := reflect.TypeOf(err)
358-
if t.Kind() == reflect.Ptr {
359-
c.Error = t.Elem()
360-
} else {
361-
c.Error = t
362-
}
357+
c.Error = getType(err)
363358
return c
364359
}
365360

@@ -463,7 +458,7 @@ func (c *Client) SetTimeout(timeout time.Duration) *Client {
463458
c.transport.Dial = func(network, addr string) (net.Conn, error) {
464459
conn, err := net.DialTimeout(network, addr, timeout)
465460
if err != nil {
466-
c.Log.Printf("Error: %v", err)
461+
c.Log.Printf("ERROR [%v]", err)
467462
return nil, err
468463
}
469464
conn.SetDeadline(time.Now().Add(timeout))
@@ -484,7 +479,7 @@ func (c *Client) SetProxy(proxyURL string) *Client {
484479
if pURL, err := url.Parse(proxyURL); err == nil {
485480
c.transport.Proxy = http.ProxyURL(pURL)
486481
} else {
487-
c.Log.Printf("ERROR: %v", err)
482+
c.Log.Printf("ERROR [%v]", err)
488483
}
489484

490485
return c
@@ -643,6 +638,24 @@ func (r *Request) SetQueryParams(params map[string]string) *Request {
643638
return r
644639
}
645640

641+
// SetQueryString method provides ability to use string as an input to set URL query string for the request.
642+
//
643+
// Using String as an input
644+
// resty.R().
645+
// SetQueryString("productId=232&template=fresh-sample&cat=resty&source=google&kw=buy a lot more")
646+
//
647+
func (r *Request) SetQueryString(query string) *Request {
648+
values, err := url.ParseQuery(strings.TrimSpace(query))
649+
if err == nil {
650+
for p, _ := range values {
651+
r.QueryParam.Add(p, values.Get(p))
652+
}
653+
} else {
654+
r.client.Log.Printf("ERROR [%v]", err)
655+
}
656+
return r
657+
}
658+
646659
// SetFormData method sets Form parameters and its values in the current request.
647660
// It's applicable only HTTP method `POST` and `PUT` and requets content type would be set as
648661
// `application/x-www-form-urlencoded`.
@@ -934,9 +947,7 @@ func IsStringEmpty(str string) bool {
934947
// DetectContentType method is used to figure out `Request.Body` content type for request header
935948
func DetectContentType(body interface{}) string {
936949
contentType := plainTextType
937-
kind := reflect.ValueOf(body).Kind()
938-
939-
switch kind {
950+
switch getBaseKind(body) {
940951
case reflect.Struct, reflect.Map:
941952
contentType = jsonContentType
942953
case reflect.String:
@@ -970,14 +981,7 @@ func Unmarshal(ct string, b []byte, d interface{}) (err error) {
970981
}
971982

972983
func getLogger(w io.Writer) *log.Logger {
973-
var l *log.Logger
974-
if w == nil {
975-
l = log.New(os.Stderr, "RESTY ", log.LstdFlags)
976-
} else {
977-
l = log.New(w, "RESTY ", log.LstdFlags)
978-
}
979-
980-
return l
984+
return log.New(w, "RESTY ", log.LstdFlags)
981985
}
982986

983987
func addFile(w *multipart.Writer, fieldName, path string) error {
@@ -998,11 +1002,10 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
9981002

9991003
func getRequestBodyString(r *Request) (body string) {
10001004
body = "***** NO CONTENT *****"
1001-
if r.Method == POST || r.Method == PUT || r.Method == PATCH {
1005+
if isPayloadSupported(r.Method) {
10021006
// multipart/form-data OR form data
10031007
if r.isMultiPart || r.isFormData {
10041008
body = string(r.bodyBuf.Bytes())
1005-
10061009
return
10071010
}
10081011

@@ -1062,10 +1065,25 @@ func getResponseBodyString(res *Response) string {
10621065
}
10631066

10641067
func getPointer(v interface{}) interface{} {
1065-
rv := reflect.TypeOf(v)
1066-
if rv.Kind() != reflect.Ptr {
1067-
return reflect.New(rv).Interface()
1068+
vv := reflect.ValueOf(v)
1069+
if vv.Kind() == reflect.Ptr {
1070+
return v
10681071
}
1072+
return reflect.New(vv.Type()).Interface()
1073+
}
10691074

1070-
return v
1075+
func isPayloadSupported(m string) bool {
1076+
return (m == POST || m == PUT || m == DELETE || m == PATCH)
1077+
}
1078+
1079+
func getBaseKind(v interface{}) reflect.Kind {
1080+
return getType(v).Kind()
1081+
}
1082+
1083+
func getType(v interface{}) reflect.Type {
1084+
vv := reflect.ValueOf(v)
1085+
if vv.Kind() == reflect.Ptr {
1086+
return vv.Elem().Type()
1087+
}
1088+
return vv.Type()
10711089
}

default.go

+26-25
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"net/http"
1111
"net/http/cookiejar"
1212
"net/url"
13+
"os"
1314
"time"
1415

1516
"golang.org/x/net/publicsuffix"
@@ -39,7 +40,7 @@ func New() *Client {
3940
Token: "",
4041
Cookies: make([]*http.Cookie, 0),
4142
Debug: false,
42-
Log: getLogger(nil),
43+
Log: getLogger(os.Stderr),
4344
httpClient: &http.Client{Jar: cookieJar},
4445
transport: &http.Transport{},
4546
}
@@ -72,122 +73,122 @@ func R() *Request {
7273
return DefaultClient.R()
7374
}
7475

75-
// SetHostURL sets Host URL. See Client.SetHostURL for more information.
76+
// SetHostURL sets Host URL. See `Client.SetHostURL for more information.
7677
func SetHostURL(url string) *Client {
7778
return DefaultClient.SetHostURL(url)
7879
}
7980

80-
// SetHeader sets single header. See Client.SetHeader for more information.
81+
// SetHeader sets single header. See `Client.SetHeader` for more information.
8182
func SetHeader(header, value string) *Client {
8283
return DefaultClient.SetHeader(header, value)
8384
}
8485

85-
// SetHeaders sets multiple headers. See Client.SetHeaders for more information.
86+
// SetHeaders sets multiple headers. See `Client.SetHeaders` for more information.
8687
func SetHeaders(headers map[string]string) *Client {
8788
return DefaultClient.SetHeaders(headers)
8889
}
8990

90-
// SetCookie sets single cookie object. See Client.SetCookie for more information.
91+
// SetCookie sets single cookie object. See `Client.SetCookie` for more information.
9192
func SetCookie(hc *http.Cookie) *Client {
9293
return DefaultClient.SetCookie(hc)
9394
}
9495

95-
// SetCookies sets multiple cookie object. See Client.SetCookies for more information.
96+
// SetCookies sets multiple cookie object. See `Client.SetCookies` for more information.
9697
func SetCookies(cs []*http.Cookie) *Client {
9798
return DefaultClient.SetCookies(cs)
9899
}
99100

100-
// SetQueryParam method sets single paramater and its value. See Client.SetQueryParam for more information.
101+
// SetQueryParam method sets single paramater and its value. See `Client.SetQueryParam` for more information.
101102
func SetQueryParam(param, value string) *Client {
102103
return DefaultClient.SetQueryParam(param, value)
103104
}
104105

105-
// SetQueryParams method sets multiple paramaters and its value. See Client.SetQueryParams for more information.
106+
// SetQueryParams method sets multiple paramaters and its value. See `Client.SetQueryParams` for more information.
106107
func SetQueryParams(params map[string]string) *Client {
107108
return DefaultClient.SetQueryParams(params)
108109
}
109110

110-
// SetFormData method sets Form parameters and its values. See Client.SetFormData for more information.
111+
// SetFormData method sets Form parameters and its values. See `Client.SetFormData` for more information.
111112
func SetFormData(data map[string]string) *Client {
112113
return DefaultClient.SetFormData(data)
113114
}
114115

115-
// SetBasicAuth method sets the basic authentication header. See Client.SetBasicAuth for more information.
116+
// SetBasicAuth method sets the basic authentication header. See `Client.SetBasicAuth` for more information.
116117
func SetBasicAuth(username, password string) *Client {
117118
return DefaultClient.SetBasicAuth(username, password)
118119
}
119120

120-
// SetAuthToken method sets bearer auth token header. See Client.SetAuthToken for more information.
121+
// SetAuthToken method sets bearer auth token header. See `Client.SetAuthToken` for more information.
121122
func SetAuthToken(token string) *Client {
122123
return DefaultClient.SetAuthToken(token)
123124
}
124125

125-
// OnBeforeRequest method sets request middleware. See Client.OnBeforeRequest for more information.
126+
// OnBeforeRequest method sets request middleware. See `Client.OnBeforeRequest` for more information.
126127
func OnBeforeRequest(m func(*Client, *Request) error) *Client {
127128
return DefaultClient.OnBeforeRequest(m)
128129
}
129130

130-
// OnAfterResponse method sets response middleware. See Client.OnAfterResponse for more information.
131+
// OnAfterResponse method sets response middleware. See `Client.OnAfterResponse` for more information.
131132
func OnAfterResponse(m func(*Client, *Response) error) *Client {
132133
return DefaultClient.OnAfterResponse(m)
133134
}
134135

135-
// SetDebug method enables the debug mode. See Client.SetDebug for more information.
136+
// SetDebug method enables the debug mode. See `Client.SetDebug` for more information.
136137
func SetDebug(d bool) *Client {
137138
return DefaultClient.SetDebug(d)
138139
}
139140

140-
// SetLogger method sets given writer for logging. See Client.SetLogger for more information.
141+
// SetLogger method sets given writer for logging. See `Client.SetLogger` for more information.
141142
func SetLogger(w io.Writer) *Client {
142143
return DefaultClient.SetLogger(w)
143144
}
144145

145-
// SetContentLength method enables `Content-Length` value. See Client.SetContentLength for more information.
146+
// SetContentLength method enables `Content-Length` value. See `Client.SetContentLength` for more information.
146147
func SetContentLength(l bool) *Client {
147148
return DefaultClient.SetContentLength(l)
148149
}
149150

150-
// SetError method is to register the global or client common `Error` object. See Client.SetError for more information.
151+
// SetError method is to register the global or client common `Error` object. See `Client.SetError` for more information.
151152
func SetError(err interface{}) *Client {
152153
return DefaultClient.SetError(err)
153154
}
154155

155-
// SetRedirectPolicy method sets the client redirect poilicy. See Client.SetRedirectPolicy for more information.
156+
// SetRedirectPolicy method sets the client redirect poilicy. See `Client.SetRedirectPolicy` for more information.
156157
func SetRedirectPolicy(policies ...interface{}) *Client {
157158
return DefaultClient.SetRedirectPolicy(policies...)
158159
}
159160

160-
// SetHTTPMode method sets go-resty mode into HTTP. See Client.SetMode for more information.
161+
// SetHTTPMode method sets go-resty mode into HTTP. See `Client.SetMode` for more information.
161162
func SetHTTPMode() *Client {
162163
return DefaultClient.SetHTTPMode()
163164
}
164165

165-
// SetRESTMode method sets go-resty mode into RESTful. See Client.SetMode for more information.
166+
// SetRESTMode method sets go-resty mode into RESTful. See `Client.SetMode` for more information.
166167
func SetRESTMode() *Client {
167168
return DefaultClient.SetRESTMode()
168169
}
169170

170-
// Mode method returns the current client mode. See Client.Mode for more information.
171+
// Mode method returns the current client mode. See `Client.Mode` for more information.
171172
func Mode() string {
172173
return DefaultClient.Mode()
173174
}
174175

175-
// SetTLSClientConfig method sets TLSClientConfig for underling client Transport. See Client.SetTLSClientConfig for more information.
176+
// SetTLSClientConfig method sets TLSClientConfig for underling client Transport. See `Client.SetTLSClientConfig` for more information.
176177
func SetTLSClientConfig(config *tls.Config) *Client {
177178
return DefaultClient.SetTLSClientConfig(config)
178179
}
179180

180-
// SetTimeout method sets timeout for request. See Client.SetTimeout for more information.
181+
// SetTimeout method sets timeout for request. See `Client.SetTimeout` for more information.
181182
func SetTimeout(timeout time.Duration) *Client {
182183
return DefaultClient.SetTimeout(timeout)
183184
}
184185

185-
// SetProxy method sets Proxy for request. See Client.SetProxy for more information.
186+
// SetProxy method sets Proxy for request. See `Client.SetProxy` for more information.
186187
func SetProxy(proxyURL string) *Client {
187188
return DefaultClient.SetProxy(proxyURL)
188189
}
189190

190-
// RemoveProxy method removes the proxy configuration. See Client.RemoveProxy for more information.
191+
// RemoveProxy method removes the proxy configuration. See `Client.RemoveProxy` for more information.
191192
func RemoveProxy() *Client {
192193
return DefaultClient.RemoveProxy()
193194
}

middleware.go

+2-6
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func parseRequestHeader(c *Client, r *Request) error {
8181
}
8282

8383
func parseRequestBody(c *Client, r *Request) (err error) {
84-
if r.Method == POST || r.Method == PUT || r.Method == PATCH {
84+
if isPayloadSupported(r.Method) {
8585
// Handling Multipart
8686
if r.isMultiPart && !(r.Method == PATCH) {
8787
r.bodyBuf = &bytes.Buffer{}
@@ -136,11 +136,7 @@ func parseRequestBody(c *Client, r *Request) (err error) {
136136
}
137137

138138
var bodyBytes []byte
139-
kind := reflect.ValueOf(r.Body).Kind()
140-
if kind == reflect.Ptr {
141-
kind = reflect.TypeOf(r.Body).Elem().Kind()
142-
}
143-
139+
kind := getBaseKind(r.Body)
144140
if IsJSONType(contentType) && (kind == reflect.Struct || kind == reflect.Map) {
145141
bodyBytes, err = json.Marshal(r.Body)
146142
} else if IsXMLType(contentType) && (kind == reflect.Struct) {

resty.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ Package resty provides simple HTTP and REST client for Go inspired by Ruby rest-
99
package resty
1010

1111
// go-resty version no
12-
var Version = "0.2.3"
12+
var Version = "0.3"

0 commit comments

Comments
 (0)