1// Copyright (c) 2015-2019 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.
2// resty source code and usage is governed by a MIT style
3// license that can be found in the LICENSE file.
4
5package resty
6
7import (
8	"crypto/tls"
9	"encoding/json"
10	"io"
11	"math"
12	"net/http"
13	"net/http/cookiejar"
14	"net/url"
15	"os"
16	"time"
17
18	"golang.org/x/net/publicsuffix"
19)
20
21// DefaultClient of resty
22var DefaultClient *Client
23
24// New method creates a new go-resty client.
25func New() *Client {
26	cookieJar, _ := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
27	return createClient(&http.Client{Jar: cookieJar})
28}
29
30// NewWithClient method create a new go-resty client with given `http.Client`.
31func NewWithClient(hc *http.Client) *Client {
32	return createClient(hc)
33}
34
35// R creates a new resty request object, it is used form a HTTP/RESTful request
36// such as GET, POST, PUT, DELETE, HEAD, PATCH and OPTIONS.
37func R() *Request {
38	return DefaultClient.R()
39}
40
41// NewRequest is an alias for R(). Creates a new resty request object, it is used form a HTTP/RESTful request
42// such as GET, POST, PUT, DELETE, HEAD, PATCH and OPTIONS.
43func NewRequest() *Request {
44	return R()
45}
46
47// SetHostURL sets Host URL. See `Client.SetHostURL for more information.
48func SetHostURL(url string) *Client {
49	return DefaultClient.SetHostURL(url)
50}
51
52// SetHeader sets single header. See `Client.SetHeader` for more information.
53func SetHeader(header, value string) *Client {
54	return DefaultClient.SetHeader(header, value)
55}
56
57// SetHeaders sets multiple headers. See `Client.SetHeaders` for more information.
58func SetHeaders(headers map[string]string) *Client {
59	return DefaultClient.SetHeaders(headers)
60}
61
62// SetCookieJar sets custom http.CookieJar. See `Client.SetCookieJar` for more information.
63func SetCookieJar(jar http.CookieJar) *Client {
64	return DefaultClient.SetCookieJar(jar)
65}
66
67// SetCookie sets single cookie object. See `Client.SetCookie` for more information.
68func SetCookie(hc *http.Cookie) *Client {
69	return DefaultClient.SetCookie(hc)
70}
71
72// SetCookies sets multiple cookie object. See `Client.SetCookies` for more information.
73func SetCookies(cs []*http.Cookie) *Client {
74	return DefaultClient.SetCookies(cs)
75}
76
77// SetQueryParam method sets single parameter and its value. See `Client.SetQueryParam` for more information.
78func SetQueryParam(param, value string) *Client {
79	return DefaultClient.SetQueryParam(param, value)
80}
81
82// SetQueryParams method sets multiple parameters and its value. See `Client.SetQueryParams` for more information.
83func SetQueryParams(params map[string]string) *Client {
84	return DefaultClient.SetQueryParams(params)
85}
86
87// SetFormData method sets Form parameters and its values. See `Client.SetFormData` for more information.
88func SetFormData(data map[string]string) *Client {
89	return DefaultClient.SetFormData(data)
90}
91
92// SetBasicAuth method sets the basic authentication header. See `Client.SetBasicAuth` for more information.
93func SetBasicAuth(username, password string) *Client {
94	return DefaultClient.SetBasicAuth(username, password)
95}
96
97// SetAuthToken method sets bearer auth token header. See `Client.SetAuthToken` for more information.
98func SetAuthToken(token string) *Client {
99	return DefaultClient.SetAuthToken(token)
100}
101
102// OnBeforeRequest method sets request middleware. See `Client.OnBeforeRequest` for more information.
103func OnBeforeRequest(m func(*Client, *Request) error) *Client {
104	return DefaultClient.OnBeforeRequest(m)
105}
106
107// OnAfterResponse method sets response middleware. See `Client.OnAfterResponse` for more information.
108func OnAfterResponse(m func(*Client, *Response) error) *Client {
109	return DefaultClient.OnAfterResponse(m)
110}
111
112// SetPreRequestHook method sets the pre-request hook. See `Client.SetPreRequestHook` for more information.
113func SetPreRequestHook(h func(*Client, *Request) error) *Client {
114	return DefaultClient.SetPreRequestHook(h)
115}
116
117// SetDebug method enables the debug mode. See `Client.SetDebug` for more information.
118func SetDebug(d bool) *Client {
119	return DefaultClient.SetDebug(d)
120}
121
122// SetDebugBodyLimit method sets the response body limit for debug mode. See `Client.SetDebugBodyLimit` for more information.
123func SetDebugBodyLimit(sl int64) *Client {
124	return DefaultClient.SetDebugBodyLimit(sl)
125}
126
127// SetAllowGetMethodPayload method allows the GET method with payload. See `Client.SetAllowGetMethodPayload` for more information.
128func SetAllowGetMethodPayload(a bool) *Client {
129	return DefaultClient.SetAllowGetMethodPayload(a)
130}
131
132// SetRetryCount method sets the retry count. See `Client.SetRetryCount` for more information.
133func SetRetryCount(count int) *Client {
134	return DefaultClient.SetRetryCount(count)
135}
136
137// SetRetryWaitTime method sets the retry wait time. See `Client.SetRetryWaitTime` for more information.
138func SetRetryWaitTime(waitTime time.Duration) *Client {
139	return DefaultClient.SetRetryWaitTime(waitTime)
140}
141
142// SetRetryMaxWaitTime method sets the retry max wait time. See `Client.SetRetryMaxWaitTime` for more information.
143func SetRetryMaxWaitTime(maxWaitTime time.Duration) *Client {
144	return DefaultClient.SetRetryMaxWaitTime(maxWaitTime)
145}
146
147// AddRetryCondition method appends check function for retry. See `Client.AddRetryCondition` for more information.
148func AddRetryCondition(condition RetryConditionFunc) *Client {
149	return DefaultClient.AddRetryCondition(condition)
150}
151
152// SetDisableWarn method disables warning comes from `go-resty` client. See `Client.SetDisableWarn` for more information.
153func SetDisableWarn(d bool) *Client {
154	return DefaultClient.SetDisableWarn(d)
155}
156
157// SetLogger method sets given writer for logging. See `Client.SetLogger` for more information.
158func SetLogger(w io.Writer) *Client {
159	return DefaultClient.SetLogger(w)
160}
161
162// SetContentLength method enables `Content-Length` value. See `Client.SetContentLength` for more information.
163func SetContentLength(l bool) *Client {
164	return DefaultClient.SetContentLength(l)
165}
166
167// SetError method is to register the global or client common `Error` object. See `Client.SetError` for more information.
168func SetError(err interface{}) *Client {
169	return DefaultClient.SetError(err)
170}
171
172// SetRedirectPolicy method sets the client redirect poilicy. See `Client.SetRedirectPolicy` for more information.
173func SetRedirectPolicy(policies ...interface{}) *Client {
174	return DefaultClient.SetRedirectPolicy(policies...)
175}
176
177// SetHTTPMode method sets go-resty mode into HTTP. See `Client.SetMode` for more information.
178func SetHTTPMode() *Client {
179	return DefaultClient.SetHTTPMode()
180}
181
182// SetRESTMode method sets go-resty mode into RESTful. See `Client.SetMode` for more information.
183func SetRESTMode() *Client {
184	return DefaultClient.SetRESTMode()
185}
186
187// Mode method returns the current client mode. See `Client.Mode` for more information.
188func Mode() string {
189	return DefaultClient.Mode()
190}
191
192// SetTLSClientConfig method sets TLSClientConfig for underling client Transport. See `Client.SetTLSClientConfig` for more information.
193func SetTLSClientConfig(config *tls.Config) *Client {
194	return DefaultClient.SetTLSClientConfig(config)
195}
196
197// SetTimeout method sets timeout for request. See `Client.SetTimeout` for more information.
198func SetTimeout(timeout time.Duration) *Client {
199	return DefaultClient.SetTimeout(timeout)
200}
201
202// SetProxy method sets Proxy for request. See `Client.SetProxy` for more information.
203func SetProxy(proxyURL string) *Client {
204	return DefaultClient.SetProxy(proxyURL)
205}
206
207// RemoveProxy method removes the proxy configuration. See `Client.RemoveProxy` for more information.
208func RemoveProxy() *Client {
209	return DefaultClient.RemoveProxy()
210}
211
212// SetCertificates method helps to set client certificates into resty conveniently.
213// See `Client.SetCertificates` for more information and example.
214func SetCertificates(certs ...tls.Certificate) *Client {
215	return DefaultClient.SetCertificates(certs...)
216}
217
218// SetRootCertificate method helps to add one or more root certificates into resty client.
219// See `Client.SetRootCertificate` for more information.
220func SetRootCertificate(pemFilePath string) *Client {
221	return DefaultClient.SetRootCertificate(pemFilePath)
222}
223
224// SetOutputDirectory method sets output directory. See `Client.SetOutputDirectory` for more information.
225func SetOutputDirectory(dirPath string) *Client {
226	return DefaultClient.SetOutputDirectory(dirPath)
227}
228
229// SetTransport method sets custom `*http.Transport` or any `http.RoundTripper`
230// compatible interface implementation in the resty client.
231// See `Client.SetTransport` for more information.
232func SetTransport(transport http.RoundTripper) *Client {
233	return DefaultClient.SetTransport(transport)
234}
235
236// SetScheme method sets custom scheme in the resty client.
237// See `Client.SetScheme` for more information.
238func SetScheme(scheme string) *Client {
239	return DefaultClient.SetScheme(scheme)
240}
241
242// SetCloseConnection method sets close connection value in the resty client.
243// See `Client.SetCloseConnection` for more information.
244func SetCloseConnection(close bool) *Client {
245	return DefaultClient.SetCloseConnection(close)
246}
247
248// SetDoNotParseResponse method instructs `Resty` not to parse the response body automatically.
249// See `Client.SetDoNotParseResponse` for more information.
250func SetDoNotParseResponse(parse bool) *Client {
251	return DefaultClient.SetDoNotParseResponse(parse)
252}
253
254// SetPathParams method sets the Request path parameter key-value pairs. See
255// `Client.SetPathParams` for more information.
256func SetPathParams(params map[string]string) *Client {
257	return DefaultClient.SetPathParams(params)
258}
259
260// IsProxySet method returns the true if proxy is set on client otherwise false.
261// See `Client.IsProxySet` for more information.
262func IsProxySet() bool {
263	return DefaultClient.IsProxySet()
264}
265
266// GetClient method returns the current `http.Client` used by the default resty client.
267func GetClient() *http.Client {
268	return DefaultClient.httpClient
269}
270
271//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
272// Unexported methods
273//___________________________________
274
275func createClient(hc *http.Client) *Client {
276	c := &Client{
277		HostURL:            "",
278		QueryParam:         url.Values{},
279		FormData:           url.Values{},
280		Header:             http.Header{},
281		UserInfo:           nil,
282		Token:              "",
283		Cookies:            make([]*http.Cookie, 0),
284		Debug:              false,
285		Log:                getLogger(os.Stderr),
286		RetryCount:         0,
287		RetryWaitTime:      defaultWaitTime,
288		RetryMaxWaitTime:   defaultMaxWaitTime,
289		JSONMarshal:        json.Marshal,
290		JSONUnmarshal:      json.Unmarshal,
291		jsonEscapeHTML:     true,
292		httpClient:         hc,
293		debugBodySizeLimit: math.MaxInt32,
294		pathParams:         make(map[string]string),
295	}
296
297	// Log Prefix
298	c.SetLogPrefix("RESTY ")
299
300	// Default redirect policy
301	c.SetRedirectPolicy(NoRedirectPolicy())
302
303	// default before request middlewares
304	c.beforeRequest = []func(*Client, *Request) error{
305		parseRequestURL,
306		parseRequestHeader,
307		parseRequestBody,
308		createHTTPRequest,
309		addCredentials,
310	}
311
312	// user defined request middlewares
313	c.udBeforeRequest = []func(*Client, *Request) error{}
314
315	// default after response middlewares
316	c.afterResponse = []func(*Client, *Response) error{
317		responseLogger,
318		parseResponseBody,
319		saveResponseIntoFile,
320	}
321
322	return c
323}
324
325func init() {
326	DefaultClient = New()
327}
328