Skip to content

Commit

Permalink
Merging implementation of #8 & #11
Browse files Browse the repository at this point in the history
  • Loading branch information
jeevatkm committed Oct 8, 2015
2 parents f8960ae + c9740e0 commit 17fa68e
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 59 deletions.
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Simple HTTP and REST client for Go inspired by Ruby rest-client. Provides notabl
* Choose between HTTP and RESTful mode. Default is RESTful
* `HTTP` - default upto 10 redirects and no automatic response unmarshal
* `RESTful` - default no redirects and automatic response unmarshal for `JSON` & `XML`
* Client settings like Timeout, RedirectPolicy, Proxy and TLSClientConfig
* Client settings like `Timeout`, `RedirectPolicy`, `Proxy` and `TLSClientConfig`
* Client API design
* Have client level settings & options and also override at Request level if you want to
* [Request](https://godoc.org/github.com/go-resty/resty#Client.OnBeforeRequest) and [Response](https://godoc.org/github.com/go-resty/resty#Client.OnAfterResponse) middleware
Expand All @@ -38,7 +38,7 @@ resty tested with Go 1.2 and above.
* FlexibleRedirectPolicy
* DomainCheckRedirectPolicy
* etc. [more info](redirect.go)
* Write Cookies to file from CookiesJar (upcoming)
* Persist Cookies into file in JSON format from resty client (upcoming)
* etc.

## Installation
Expand Down Expand Up @@ -104,6 +104,14 @@ resp, err := resty.R().
SetHeader("Accept", "application/json").
SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F").
Get("/search_result")


// Sample of using Request.SetQueryString method
resp, err := resty.R().
SetQueryString("productId=232&template=fresh-sample&cat=resty&source=google&kw=buy a lot more").
SetHeader("Accept", "application/json").
SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F").
Get("/show_product")
```

#### Various POST method combinations
Expand Down
68 changes: 43 additions & 25 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,12 +354,7 @@ func (c *Client) SetContentLength(l bool) *Client {
// resty.SetError(Error{})
//
func (c *Client) SetError(err interface{}) *Client {
t := reflect.TypeOf(err)
if t.Kind() == reflect.Ptr {
c.Error = t.Elem()
} else {
c.Error = t
}
c.Error = getType(err)
return c
}

Expand Down Expand Up @@ -463,7 +458,7 @@ func (c *Client) SetTimeout(timeout time.Duration) *Client {
c.transport.Dial = func(network, addr string) (net.Conn, error) {
conn, err := net.DialTimeout(network, addr, timeout)
if err != nil {
c.Log.Printf("Error: %v", err)
c.Log.Printf("ERROR [%v]", err)
return nil, err
}
conn.SetDeadline(time.Now().Add(timeout))
Expand All @@ -484,7 +479,7 @@ func (c *Client) SetProxy(proxyURL string) *Client {
if pURL, err := url.Parse(proxyURL); err == nil {
c.transport.Proxy = http.ProxyURL(pURL)
} else {
c.Log.Printf("ERROR: %v", err)
c.Log.Printf("ERROR [%v]", err)
}

return c
Expand Down Expand Up @@ -643,6 +638,24 @@ func (r *Request) SetQueryParams(params map[string]string) *Request {
return r
}

// SetQueryString method provides ability to use string as an input to set URL query string for the request.
//
// Using String as an input
// resty.R().
// SetQueryString("productId=232&template=fresh-sample&cat=resty&source=google&kw=buy a lot more")
//
func (r *Request) SetQueryString(query string) *Request {
values, err := url.ParseQuery(strings.TrimSpace(query))
if err == nil {
for p, _ := range values {
r.QueryParam.Add(p, values.Get(p))
}
} else {
r.client.Log.Printf("ERROR [%v]", err)
}
return r
}

// SetFormData method sets Form parameters and its values in the current request.
// It's applicable only HTTP method `POST` and `PUT` and requets content type would be set as
// `application/x-www-form-urlencoded`.
Expand Down Expand Up @@ -934,9 +947,7 @@ func IsStringEmpty(str string) bool {
// DetectContentType method is used to figure out `Request.Body` content type for request header
func DetectContentType(body interface{}) string {
contentType := plainTextType
kind := reflect.ValueOf(body).Kind()

switch kind {
switch getBaseKind(body) {
case reflect.Struct, reflect.Map:
contentType = jsonContentType
case reflect.String:
Expand Down Expand Up @@ -970,14 +981,7 @@ func Unmarshal(ct string, b []byte, d interface{}) (err error) {
}

func getLogger(w io.Writer) *log.Logger {
var l *log.Logger
if w == nil {
l = log.New(os.Stderr, "RESTY ", log.LstdFlags)
} else {
l = log.New(w, "RESTY ", log.LstdFlags)
}

return l
return log.New(w, "RESTY ", log.LstdFlags)
}

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

func getRequestBodyString(r *Request) (body string) {
body = "***** NO CONTENT *****"
if r.Method == POST || r.Method == PUT || r.Method == PATCH {
if isPayloadSupported(r.Method) {
// multipart/form-data OR form data
if r.isMultiPart || r.isFormData {
body = string(r.bodyBuf.Bytes())

return
}

Expand Down Expand Up @@ -1062,10 +1065,25 @@ func getResponseBodyString(res *Response) string {
}

func getPointer(v interface{}) interface{} {
rv := reflect.TypeOf(v)
if rv.Kind() != reflect.Ptr {
return reflect.New(rv).Interface()
vv := reflect.ValueOf(v)
if vv.Kind() == reflect.Ptr {
return v
}
return reflect.New(vv.Type()).Interface()
}

return v
func isPayloadSupported(m string) bool {
return (m == POST || m == PUT || m == DELETE || m == PATCH)
}

func getBaseKind(v interface{}) reflect.Kind {
return getType(v).Kind()
}

func getType(v interface{}) reflect.Type {
vv := reflect.ValueOf(v)
if vv.Kind() == reflect.Ptr {
return vv.Elem().Type()
}
return vv.Type()
}
51 changes: 26 additions & 25 deletions default.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"net/http"
"net/http/cookiejar"
"net/url"
"os"
"time"

"golang.org/x/net/publicsuffix"
Expand Down Expand Up @@ -39,7 +40,7 @@ func New() *Client {
Token: "",
Cookies: make([]*http.Cookie, 0),
Debug: false,
Log: getLogger(nil),
Log: getLogger(os.Stderr),
httpClient: &http.Client{Jar: cookieJar},
transport: &http.Transport{},
}
Expand Down Expand Up @@ -72,122 +73,122 @@ func R() *Request {
return DefaultClient.R()
}

// SetHostURL sets Host URL. See Client.SetHostURL for more information.
// SetHostURL sets Host URL. See `Client.SetHostURL for more information.
func SetHostURL(url string) *Client {
return DefaultClient.SetHostURL(url)
}

// SetHeader sets single header. See Client.SetHeader for more information.
// SetHeader sets single header. See `Client.SetHeader` for more information.
func SetHeader(header, value string) *Client {
return DefaultClient.SetHeader(header, value)
}

// SetHeaders sets multiple headers. See Client.SetHeaders for more information.
// SetHeaders sets multiple headers. See `Client.SetHeaders` for more information.
func SetHeaders(headers map[string]string) *Client {
return DefaultClient.SetHeaders(headers)
}

// SetCookie sets single cookie object. See Client.SetCookie for more information.
// SetCookie sets single cookie object. See `Client.SetCookie` for more information.
func SetCookie(hc *http.Cookie) *Client {
return DefaultClient.SetCookie(hc)
}

// SetCookies sets multiple cookie object. See Client.SetCookies for more information.
// SetCookies sets multiple cookie object. See `Client.SetCookies` for more information.
func SetCookies(cs []*http.Cookie) *Client {
return DefaultClient.SetCookies(cs)
}

// SetQueryParam method sets single paramater and its value. See Client.SetQueryParam for more information.
// SetQueryParam method sets single paramater and its value. See `Client.SetQueryParam` for more information.
func SetQueryParam(param, value string) *Client {
return DefaultClient.SetQueryParam(param, value)
}

// SetQueryParams method sets multiple paramaters and its value. See Client.SetQueryParams for more information.
// SetQueryParams method sets multiple paramaters and its value. See `Client.SetQueryParams` for more information.
func SetQueryParams(params map[string]string) *Client {
return DefaultClient.SetQueryParams(params)
}

// SetFormData method sets Form parameters and its values. See Client.SetFormData for more information.
// SetFormData method sets Form parameters and its values. See `Client.SetFormData` for more information.
func SetFormData(data map[string]string) *Client {
return DefaultClient.SetFormData(data)
}

// SetBasicAuth method sets the basic authentication header. See Client.SetBasicAuth for more information.
// SetBasicAuth method sets the basic authentication header. See `Client.SetBasicAuth` for more information.
func SetBasicAuth(username, password string) *Client {
return DefaultClient.SetBasicAuth(username, password)
}

// SetAuthToken method sets bearer auth token header. See Client.SetAuthToken for more information.
// SetAuthToken method sets bearer auth token header. See `Client.SetAuthToken` for more information.
func SetAuthToken(token string) *Client {
return DefaultClient.SetAuthToken(token)
}

// OnBeforeRequest method sets request middleware. See Client.OnBeforeRequest for more information.
// OnBeforeRequest method sets request middleware. See `Client.OnBeforeRequest` for more information.
func OnBeforeRequest(m func(*Client, *Request) error) *Client {
return DefaultClient.OnBeforeRequest(m)
}

// OnAfterResponse method sets response middleware. See Client.OnAfterResponse for more information.
// OnAfterResponse method sets response middleware. See `Client.OnAfterResponse` for more information.
func OnAfterResponse(m func(*Client, *Response) error) *Client {
return DefaultClient.OnAfterResponse(m)
}

// SetDebug method enables the debug mode. See Client.SetDebug for more information.
// SetDebug method enables the debug mode. See `Client.SetDebug` for more information.
func SetDebug(d bool) *Client {
return DefaultClient.SetDebug(d)
}

// SetLogger method sets given writer for logging. See Client.SetLogger for more information.
// SetLogger method sets given writer for logging. See `Client.SetLogger` for more information.
func SetLogger(w io.Writer) *Client {
return DefaultClient.SetLogger(w)
}

// SetContentLength method enables `Content-Length` value. See Client.SetContentLength for more information.
// SetContentLength method enables `Content-Length` value. See `Client.SetContentLength` for more information.
func SetContentLength(l bool) *Client {
return DefaultClient.SetContentLength(l)
}

// SetError method is to register the global or client common `Error` object. See Client.SetError for more information.
// SetError method is to register the global or client common `Error` object. See `Client.SetError` for more information.
func SetError(err interface{}) *Client {
return DefaultClient.SetError(err)
}

// SetRedirectPolicy method sets the client redirect poilicy. See Client.SetRedirectPolicy for more information.
// SetRedirectPolicy method sets the client redirect poilicy. See `Client.SetRedirectPolicy` for more information.
func SetRedirectPolicy(policies ...interface{}) *Client {
return DefaultClient.SetRedirectPolicy(policies...)
}

// SetHTTPMode method sets go-resty mode into HTTP. See Client.SetMode for more information.
// SetHTTPMode method sets go-resty mode into HTTP. See `Client.SetMode` for more information.
func SetHTTPMode() *Client {
return DefaultClient.SetHTTPMode()
}

// SetRESTMode method sets go-resty mode into RESTful. See Client.SetMode for more information.
// SetRESTMode method sets go-resty mode into RESTful. See `Client.SetMode` for more information.
func SetRESTMode() *Client {
return DefaultClient.SetRESTMode()
}

// Mode method returns the current client mode. See Client.Mode for more information.
// Mode method returns the current client mode. See `Client.Mode` for more information.
func Mode() string {
return DefaultClient.Mode()
}

// SetTLSClientConfig method sets TLSClientConfig for underling client Transport. See Client.SetTLSClientConfig for more information.
// SetTLSClientConfig method sets TLSClientConfig for underling client Transport. See `Client.SetTLSClientConfig` for more information.
func SetTLSClientConfig(config *tls.Config) *Client {
return DefaultClient.SetTLSClientConfig(config)
}

// SetTimeout method sets timeout for request. See Client.SetTimeout for more information.
// SetTimeout method sets timeout for request. See `Client.SetTimeout` for more information.
func SetTimeout(timeout time.Duration) *Client {
return DefaultClient.SetTimeout(timeout)
}

// SetProxy method sets Proxy for request. See Client.SetProxy for more information.
// SetProxy method sets Proxy for request. See `Client.SetProxy` for more information.
func SetProxy(proxyURL string) *Client {
return DefaultClient.SetProxy(proxyURL)
}

// RemoveProxy method removes the proxy configuration. See Client.RemoveProxy for more information.
// RemoveProxy method removes the proxy configuration. See `Client.RemoveProxy` for more information.
func RemoveProxy() *Client {
return DefaultClient.RemoveProxy()
}
8 changes: 2 additions & 6 deletions middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func parseRequestHeader(c *Client, r *Request) error {
}

func parseRequestBody(c *Client, r *Request) (err error) {
if r.Method == POST || r.Method == PUT || r.Method == PATCH {
if isPayloadSupported(r.Method) {
// Handling Multipart
if r.isMultiPart && !(r.Method == PATCH) {
r.bodyBuf = &bytes.Buffer{}
Expand Down Expand Up @@ -136,11 +136,7 @@ func parseRequestBody(c *Client, r *Request) (err error) {
}

var bodyBytes []byte
kind := reflect.ValueOf(r.Body).Kind()
if kind == reflect.Ptr {
kind = reflect.TypeOf(r.Body).Elem().Kind()
}

kind := getBaseKind(r.Body)
if IsJSONType(contentType) && (kind == reflect.Struct || kind == reflect.Map) {
bodyBytes, err = json.Marshal(r.Body)
} else if IsXMLType(contentType) && (kind == reflect.Struct) {
Expand Down
2 changes: 1 addition & 1 deletion resty.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ Package resty provides simple HTTP and REST client for Go inspired by Ruby rest-
package resty

// go-resty version no
var Version = "0.2.3"
var Version = "0.3"
Loading

0 comments on commit 17fa68e

Please sign in to comment.