Source File
client.go
Belonging Package
github.com/go-resty/resty/v2
// Copyright (c) 2015-2023 Jeevanandam M (jeeva@myjeeva.com), All rights reserved.// resty source code and usage is governed by a MIT style// license that can be found in the LICENSE file.package restyimport ()const (// MethodGet HTTP methodMethodGet = "GET"// MethodPost HTTP methodMethodPost = "POST"// MethodPut HTTP methodMethodPut = "PUT"// MethodDelete HTTP methodMethodDelete = "DELETE"// MethodPatch HTTP methodMethodPatch = "PATCH"// MethodHead HTTP methodMethodHead = "HEAD"// MethodOptions HTTP methodMethodOptions = "OPTIONS")var (hdrUserAgentKey = http.CanonicalHeaderKey("User-Agent")hdrAcceptKey = http.CanonicalHeaderKey("Accept")hdrContentTypeKey = http.CanonicalHeaderKey("Content-Type")hdrContentLengthKey = http.CanonicalHeaderKey("Content-Length")hdrContentEncodingKey = http.CanonicalHeaderKey("Content-Encoding")hdrLocationKey = http.CanonicalHeaderKey("Location")hdrAuthorizationKey = http.CanonicalHeaderKey("Authorization")hdrWwwAuthenticateKey = http.CanonicalHeaderKey("WWW-Authenticate")plainTextType = "text/plain; charset=utf-8"jsonContentType = "application/json"formContentType = "application/x-www-form-urlencoded"jsonCheck = regexp.MustCompile(`(?i:(application|text)/(.*json.*)(;|$))`)xmlCheck = regexp.MustCompile(`(?i:(application|text)/(.*xml.*)(;|$))`)hdrUserAgentValue = "go-resty/" + Version + " (https://github.com/go-resty/resty)"bufPool = &sync.Pool{New: func() interface{} { return &bytes.Buffer{} }})type (// RequestMiddleware type is for request middleware, called before a request is sentRequestMiddleware func(*Client, *Request) error// ResponseMiddleware type is for response middleware, called after a response has been receivedResponseMiddleware func(*Client, *Response) error// PreRequestHook type is for the request hook, called right before the request is sentPreRequestHook func(*Client, *http.Request) error// RequestLogCallback type is for request logs, called before the request is loggedRequestLogCallback func(*RequestLog) error// ResponseLogCallback type is for response logs, called before the response is loggedResponseLogCallback func(*ResponseLog) error// ErrorHook type is for reacting to request errors, called after all retries were attemptedErrorHook func(*Request, error)// SuccessHook type is for reacting to request successSuccessHook func(*Client, *Response))// Client struct is used to create Resty client with client level settings,// these settings are applicable to all the request raised from the client.//// Resty also provides an options to override most of the client settings// at request level.type Client struct {BaseURL stringHostURL string // Deprecated: use BaseURL instead. To be removed in v3.0.0 release.QueryParam url.ValuesFormData url.ValuesPathParams map[string]stringRawPathParams map[string]stringHeader http.HeaderUserInfo *UserToken stringAuthScheme stringCookies []*http.CookieError reflect.TypeDebug boolDisableWarn boolAllowGetMethodPayload boolRetryCount intRetryWaitTime time.DurationRetryMaxWaitTime time.DurationRetryConditions []RetryConditionFuncRetryHooks []OnRetryFuncRetryAfter RetryAfterFuncRetryResetReaders boolJSONMarshal func(v interface{}) ([]byte, error)JSONUnmarshal func(data []byte, v interface{}) errorXMLMarshal func(v interface{}) ([]byte, error)XMLUnmarshal func(data []byte, v interface{}) error// HeaderAuthorizationKey is used to set/access Request Authorization header// value when `SetAuthToken` option is used.HeaderAuthorizationKey stringjsonEscapeHTML boolsetContentLength boolcloseConnection boolnotParseResponse booltrace booldebugBodySizeLimit int64outputDirectory stringscheme stringlog LoggerhttpClient *http.ClientproxyURL *url.URLbeforeRequest []RequestMiddlewareudBeforeRequest []RequestMiddlewareudBeforeRequestLock sync.RWMutexpreReqHook PreRequestHooksuccessHooks []SuccessHookafterResponse []ResponseMiddlewareafterResponseLock sync.RWMutexrequestLog RequestLogCallbackresponseLog ResponseLogCallbackerrorHooks []ErrorHookinvalidHooks []ErrorHookpanicHooks []ErrorHookrateLimiter RateLimiter}// User type is to hold an username and password informationtype User struct {Username, Password string}//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾// Client methods//___________________________________// SetHostURL method is to set Host URL in the client instance. It will be used with request// raised from this client with relative URL//// // Setting HTTP address// client.SetHostURL("http://myjeeva.com")//// // Setting HTTPS address// client.SetHostURL("https://myjeeva.com")//// Deprecated: use SetBaseURL instead. To be removed in v3.0.0 release.func ( *Client) ( string) *Client {.SetBaseURL()return}// SetBaseURL method is to set Base URL in the client instance. It will be used with request// raised from this client with relative URL//// // Setting HTTP address// client.SetBaseURL("http://myjeeva.com")//// // Setting HTTPS address// client.SetBaseURL("https://myjeeva.com")//// Since v2.7.0func ( *Client) ( string) *Client {.BaseURL = strings.TrimRight(, "/").HostURL = .BaseURLreturn}// SetHeader method sets a single header field and its value in the client instance.// These headers will be applied to all requests raised from this client instance.// Also it can be overridden at request level header options.//// See `Request.SetHeader` or `Request.SetHeaders`.//// For Example: To set `Content-Type` and `Accept` as `application/json`//// client.// SetHeader("Content-Type", "application/json").// SetHeader("Accept", "application/json")func ( *Client) (, string) *Client {.Header.Set(, )return}// SetHeaders method sets multiple headers field and its values at one go in the client instance.// These headers will be applied to all requests raised from this client instance. Also it can be// overridden at request level headers options.//// See `Request.SetHeaders` or `Request.SetHeader`.//// For Example: To set `Content-Type` and `Accept` as `application/json`//// client.SetHeaders(map[string]string{// "Content-Type": "application/json",// "Accept": "application/json",// })func ( *Client) ( map[string]string) *Client {for , := range {.Header.Set(, )}return}// SetHeaderVerbatim method is to set a single header field and its value verbatim in the current request.//// For Example: To set `all_lowercase` and `UPPERCASE` as `available`.//// client.R().// SetHeaderVerbatim("all_lowercase", "available").// SetHeaderVerbatim("UPPERCASE", "available")//// Also you can override header value, which was set at client instance level.//// Since v2.6.0func ( *Client) (, string) *Client {.Header[] = []string{}return}// SetCookieJar method sets custom http.CookieJar in the resty client. Its way to override default.//// For Example: sometimes we don't want to save cookies in api contacting, we can remove the default// CookieJar in resty client.//// client.SetCookieJar(nil)func ( *Client) ( http.CookieJar) *Client {.httpClient.Jar =return}// SetCookie method appends a single cookie in the client instance.// These cookies will be added to all the request raised from this client instance.//// client.SetCookie(&http.Cookie{// Name:"go-resty",// Value:"This is cookie value",// })func ( *Client) ( *http.Cookie) *Client {.Cookies = append(.Cookies, )return}// SetCookies method sets an array of cookies in the client instance.// These cookies will be added to all the request raised from this client instance.//// cookies := []*http.Cookie{// &http.Cookie{// Name:"go-resty-1",// Value:"This is cookie 1 value",// },// &http.Cookie{// Name:"go-resty-2",// Value:"This is cookie 2 value",// },// }//// // Setting a cookies into resty// client.SetCookies(cookies)func ( *Client) ( []*http.Cookie) *Client {.Cookies = append(.Cookies, ...)return}// SetQueryParam method sets single parameter and its value in the client instance.// It will be formed as query string for the request.//// For Example: `search=kitchen%20papers&size=large`// in the URL after `?` mark. These query params will be added to all the request raised from// this client instance. Also it can be overridden at request level Query Param options.//// See `Request.SetQueryParam` or `Request.SetQueryParams`.//// client.// SetQueryParam("search", "kitchen papers").// SetQueryParam("size", "large")func ( *Client) (, string) *Client {.QueryParam.Set(, )return}// SetQueryParams method sets multiple parameters and their values at one go in the client instance.// It will be formed as query string for the request.//// For Example: `search=kitchen%20papers&size=large`// in the URL after `?` mark. These query params will be added to all the request raised from this// client instance. Also it can be overridden at request level Query Param options.//// See `Request.SetQueryParams` or `Request.SetQueryParam`.//// client.SetQueryParams(map[string]string{// "search": "kitchen papers",// "size": "large",// })func ( *Client) ( map[string]string) *Client {for , := range {.SetQueryParam(, )}return}// SetFormData method sets Form parameters and their values in the client instance.// It's applicable only HTTP method `POST` and `PUT` and request content type would be set as// `application/x-www-form-urlencoded`. These form data will be added to all the request raised from// this client instance. Also it can be overridden at request level form data.//// See `Request.SetFormData`.//// client.SetFormData(map[string]string{// "access_token": "BC594900-518B-4F7E-AC75-BD37F019E08F",// "user_id": "3455454545",// })func ( *Client) ( map[string]string) *Client {for , := range {.FormData.Set(, )}return}// SetBasicAuth method sets the basic authentication header in the HTTP request. For Example://// Authorization: Basic <base64-encoded-value>//// For Example: To set the header for username "go-resty" and password "welcome"//// client.SetBasicAuth("go-resty", "welcome")//// This basic auth information gets added to all the request raised from this client instance.// Also it can be overridden or set one at the request level is supported.//// See `Request.SetBasicAuth`.func ( *Client) (, string) *Client {.UserInfo = &User{Username: , Password: }return}// SetAuthToken method sets the auth token of the `Authorization` header for all HTTP requests.// The default auth scheme is `Bearer`, it can be customized with the method `SetAuthScheme`. For Example://// Authorization: <auth-scheme> <auth-token-value>//// For Example: To set auth token BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F//// client.SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F")//// This auth token gets added to all the requests raised from this client instance.// Also it can be overridden or set one at the request level is supported.//// See `Request.SetAuthToken`.func ( *Client) ( string) *Client {.Token =return}// SetAuthScheme method sets the auth scheme type in the HTTP request. For Example://// Authorization: <auth-scheme-value> <auth-token-value>//// For Example: To set the scheme to use OAuth//// client.SetAuthScheme("OAuth")//// This auth scheme gets added to all the requests raised from this client instance.// Also it can be overridden or set one at the request level is supported.//// Information about auth schemes can be found in RFC7235 which is linked to below// along with the page containing the currently defined official authentication schemes://// https://tools.ietf.org/html/rfc7235// https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml#authschemes//// See `Request.SetAuthToken`.func ( *Client) ( string) *Client {.AuthScheme =return}// SetDigestAuth method sets the Digest Access auth scheme for the client. If a server responds with 401 and sends// a Digest challenge in the WWW-Authenticate Header, requests will be resent with the appropriate Authorization Header.//// For Example: To set the Digest scheme with user "Mufasa" and password "Circle Of Life"//// client.SetDigestAuth("Mufasa", "Circle Of Life")//// Information about Digest Access Authentication can be found in RFC7616://// https://datatracker.ietf.org/doc/html/rfc7616//// See `Request.SetDigestAuth`.func ( *Client) (, string) *Client {:= .httpClient.Transport.OnBeforeRequest(func( *Client, *Request) error {.httpClient.Transport = &digestTransport{digestCredentials: digestCredentials{, },transport: ,}return nil}).OnAfterResponse(func( *Client, *Response) error {.httpClient.Transport =return nil})return}// R method creates a new request instance, its used for Get, Post, Put, Delete, Patch, Head, Options, etc.func ( *Client) () *Request {:= &Request{QueryParam: url.Values{},FormData: url.Values{},Header: http.Header{},Cookies: make([]*http.Cookie, 0),PathParams: map[string]string{},RawPathParams: map[string]string{},Debug: .Debug,client: ,multipartFiles: []*File{},multipartFields: []*MultipartField{},jsonEscapeHTML: .jsonEscapeHTML,log: .log,}return}// NewRequest is an alias for method `R()`. Creates a new request instance, its used for// Get, Post, Put, Delete, Patch, Head, Options, etc.func ( *Client) () *Request {return .R()}// OnBeforeRequest method appends a request middleware into the before request chain.// The user defined middlewares get applied before the default Resty request middlewares.// After all middlewares have been applied, the request is sent from Resty to the host server.//// client.OnBeforeRequest(func(c *resty.Client, r *resty.Request) error {// // Now you have access to Client and Request instance// // manipulate it as per your need//// return nil // if its success otherwise return error// })func ( *Client) ( RequestMiddleware) *Client {.udBeforeRequestLock.Lock()defer .udBeforeRequestLock.Unlock().udBeforeRequest = append(.udBeforeRequest, )return}// OnAfterResponse method appends response middleware into the after response chain.// Once we receive response from host server, default Resty response middleware// gets applied and then user assigned response middlewares applied.//// client.OnAfterResponse(func(c *resty.Client, r *resty.Response) error {// // Now you have access to Client and Response instance// // manipulate it as per your need//// return nil // if its success otherwise return error// })func ( *Client) ( ResponseMiddleware) *Client {.afterResponseLock.Lock()defer .afterResponseLock.Unlock().afterResponse = append(.afterResponse, )return}// OnError method adds a callback that will be run whenever a request execution fails.// This is called after all retries have been attempted (if any).// If there was a response from the server, the error will be wrapped in *ResponseError// which has the last response received from the server.//// client.OnError(func(req *resty.Request, err error) {// if v, ok := err.(*resty.ResponseError); ok {// // Do something with v.Response// }// // Log the error, increment a metric, etc...// })//// Out of the OnSuccess, OnError, OnInvalid, OnPanic callbacks, exactly one// set will be invoked for each call to Request.Execute() that completes.func ( *Client) ( ErrorHook) *Client {.errorHooks = append(.errorHooks, )return}// OnSuccess method adds a callback that will be run whenever a request execution// succeeds. This is called after all retries have been attempted (if any).//// Out of the OnSuccess, OnError, OnInvalid, OnPanic callbacks, exactly one// set will be invoked for each call to Request.Execute() that completes.//// Since v2.8.0func ( *Client) ( SuccessHook) *Client {.successHooks = append(.successHooks, )return}// OnInvalid method adds a callback that will be run whenever a request execution// fails before it starts because the request is invalid.//// Out of the OnSuccess, OnError, OnInvalid, OnPanic callbacks, exactly one// set will be invoked for each call to Request.Execute() that completes.//// Since v2.8.0func ( *Client) ( ErrorHook) *Client {.invalidHooks = append(.invalidHooks, )return}// OnPanic method adds a callback that will be run whenever a request execution// panics.//// Out of the OnSuccess, OnError, OnInvalid, OnPanic callbacks, exactly one// set will be invoked for each call to Request.Execute() that completes.// If an OnSuccess, OnError, or OnInvalid callback panics, then the exactly// one rule can be violated.//// Since v2.8.0func ( *Client) ( ErrorHook) *Client {.panicHooks = append(.panicHooks, )return}// SetPreRequestHook method sets the given pre-request function into resty client.// It is called right before the request is fired.//// Note: Only one pre-request hook can be registered. Use `client.OnBeforeRequest` for multiple.func ( *Client) ( PreRequestHook) *Client {if .preReqHook != nil {.log.Warnf("Overwriting an existing pre-request hook: %s", functionName())}.preReqHook =return}// SetDebug method enables the debug mode on Resty client. Client logs details of every request and response.// For `Request` it logs information such as HTTP verb, Relative URL path, Host, Headers, Body if it has one.// For `Response` it logs information such as Status, Response Time, Headers, Body if it has one.//// client.SetDebug(true)//// Also it can be enabled at request level for particular request, see `Request.SetDebug`.func ( *Client) ( bool) *Client {.Debug =return}// SetDebugBodyLimit sets the maximum size for which the response and request body will be logged in debug mode.//// client.SetDebugBodyLimit(1000000)func ( *Client) ( int64) *Client {.debugBodySizeLimit =return}// OnRequestLog method used to set request log callback into Resty. Registered callback gets// called before the resty actually logs the information.func ( *Client) ( RequestLogCallback) *Client {if .requestLog != nil {.log.Warnf("Overwriting an existing on-request-log callback from=%s to=%s",functionName(.requestLog), functionName())}.requestLog =return}// OnResponseLog method used to set response log callback into Resty. Registered callback gets// called before the resty actually logs the information.func ( *Client) ( ResponseLogCallback) *Client {if .responseLog != nil {.log.Warnf("Overwriting an existing on-response-log callback from=%s to=%s",functionName(.responseLog), functionName())}.responseLog =return}// SetDisableWarn method disables the warning message on Resty client.//// For Example: Resty warns the user when BasicAuth used on non-TLS mode.//// client.SetDisableWarn(true)func ( *Client) ( bool) *Client {.DisableWarn =return}// SetAllowGetMethodPayload method allows the GET method with payload on Resty client.//// For Example: Resty allows the user sends request with a payload on HTTP GET method.//// client.SetAllowGetMethodPayload(true)func ( *Client) ( bool) *Client {.AllowGetMethodPayload =return}// SetLogger method sets given writer for logging Resty request and response details.//// Compliant to interface `resty.Logger`.func ( *Client) ( Logger) *Client {.log =return}// SetContentLength method enables the HTTP header `Content-Length` value for every request.// By default Resty won't set `Content-Length`.//// client.SetContentLength(true)//// Also you have an option to enable for particular request. See `Request.SetContentLength`func ( *Client) ( bool) *Client {.setContentLength =return}// SetTimeout method sets timeout for request raised from client.//// client.SetTimeout(time.Duration(1 * time.Minute))func ( *Client) ( time.Duration) *Client {.httpClient.Timeout =return}// SetError method is to register the global or client common `Error` object into Resty.// It is used for automatic unmarshalling if response status code is greater than 399 and// content type either JSON or XML. Can be pointer or non-pointer.//// client.SetError(&Error{})// // OR// client.SetError(Error{})func ( *Client) ( interface{}) *Client {.Error = typeOf()return}// SetRedirectPolicy method sets the client redirect policy. Resty provides ready to use// redirect policies. Wanna create one for yourself refer to `redirect.go`.//// client.SetRedirectPolicy(FlexibleRedirectPolicy(20))//// // Need multiple redirect policies together// client.SetRedirectPolicy(FlexibleRedirectPolicy(20), DomainCheckRedirectPolicy("host1.com", "host2.net"))func ( *Client) ( ...interface{}) *Client {for , := range {if , := .(RedirectPolicy); ! {.log.Errorf("%v does not implement resty.RedirectPolicy (missing Apply method)",functionName())}}.httpClient.CheckRedirect = func( *http.Request, []*http.Request) error {for , := range {if := .(RedirectPolicy).Apply(, ); != nil {return}}return nil // looks good, go ahead}return}// SetRetryCount method enables retry on Resty client and allows you// to set no. of retry count. Resty uses a Backoff mechanism.func ( *Client) ( int) *Client {.RetryCount =return}// SetRetryWaitTime method sets default wait time to sleep before retrying// request.//// Default is 100 milliseconds.func ( *Client) ( time.Duration) *Client {.RetryWaitTime =return}// SetRetryMaxWaitTime method sets max wait time to sleep before retrying// request.//// Default is 2 seconds.func ( *Client) ( time.Duration) *Client {.RetryMaxWaitTime =return}// SetRetryAfter sets callback to calculate wait time between retries.// Default (nil) implies exponential backoff with jitterfunc ( *Client) ( RetryAfterFunc) *Client {.RetryAfter =return}// SetJSONMarshaler method sets the JSON marshaler function to marshal the request body.// By default, Resty uses `encoding/json` package to marshal the request body.//// Since v2.8.0func ( *Client) ( func( interface{}) ([]byte, error)) *Client {.JSONMarshal =return}// SetJSONUnmarshaler method sets the JSON unmarshaler function to unmarshal the response body.// By default, Resty uses `encoding/json` package to unmarshal the response body.//// Since v2.8.0func ( *Client) ( func( []byte, interface{}) error) *Client {.JSONUnmarshal =return}// SetXMLMarshaler method sets the XML marshaler function to marshal the request body.// By default, Resty uses `encoding/xml` package to marshal the request body.//// Since v2.8.0func ( *Client) ( func( interface{}) ([]byte, error)) *Client {.XMLMarshal =return}// SetXMLUnmarshaler method sets the XML unmarshaler function to unmarshal the response body.// By default, Resty uses `encoding/xml` package to unmarshal the response body.//// Since v2.8.0func ( *Client) ( func( []byte, interface{}) error) *Client {.XMLUnmarshal =return}// AddRetryCondition method adds a retry condition function to array of functions// that are checked to determine if the request is retried. The request will// retry if any of the functions return true and error is nil.//// Note: These retry conditions are applied on all Request made using this Client.// For Request specific retry conditions check *Request.AddRetryConditionfunc ( *Client) ( RetryConditionFunc) *Client {.RetryConditions = append(.RetryConditions, )return}// AddRetryAfterErrorCondition adds the basic condition of retrying after encountering// an error from the http response//// Since v2.6.0func ( *Client) () *Client {.AddRetryCondition(func( *Response, error) bool {return .IsError()})return}// AddRetryHook adds a side-effecting retry hook to an array of hooks// that will be executed on each retry.//// Since v2.6.0func ( *Client) ( OnRetryFunc) *Client {.RetryHooks = append(.RetryHooks, )return}// SetRetryResetReaders method enables the Resty client to seek the start of all// file readers given as multipart files, if the given object implements `io.ReadSeeker`.//// Since ...func ( *Client) ( bool) *Client {.RetryResetReaders =return}// SetTLSClientConfig method sets TLSClientConfig for underling client Transport.//// For Example://// // One can set custom root-certificate. Refer: http://golang.org/pkg/crypto/tls/#example_Dial// client.SetTLSClientConfig(&tls.Config{ RootCAs: roots })//// // or One can disable security check (https)// client.SetTLSClientConfig(&tls.Config{ InsecureSkipVerify: true })//// Note: This method overwrites existing `TLSClientConfig`.func ( *Client) ( *tls.Config) *Client {, := .Transport()if != nil {.log.Errorf("%v", )return}.TLSClientConfig =return}// SetProxy method sets the Proxy URL and Port for Resty client.//// client.SetProxy("http://proxyserver:8888")//// OR Without this `SetProxy` method, you could also set Proxy via environment variable.//// Refer to godoc `http.ProxyFromEnvironment`.func ( *Client) ( string) *Client {, := .Transport()if != nil {.log.Errorf("%v", )return}, := url.Parse()if != nil {.log.Errorf("%v", )return}.proxyURL =.Proxy = http.ProxyURL(.proxyURL)return}// RemoveProxy method removes the proxy configuration from Resty client//// client.RemoveProxy()func ( *Client) () *Client {, := .Transport()if != nil {.log.Errorf("%v", )return}.proxyURL = nil.Proxy = nilreturn}// SetCertificates method helps to set client certificates into Resty conveniently.func ( *Client) ( ...tls.Certificate) *Client {, := .tlsConfig()if != nil {.log.Errorf("%v", )return}.Certificates = append(.Certificates, ...)return}// SetRootCertificate method helps to add one or more root certificates into Resty client//// client.SetRootCertificate("/path/to/root/pemFile.pem")func ( *Client) ( string) *Client {, := os.ReadFile()if != nil {.log.Errorf("%v", )return}, := .tlsConfig()if != nil {.log.Errorf("%v", )return}if .RootCAs == nil {.RootCAs = x509.NewCertPool()}.RootCAs.AppendCertsFromPEM()return}// SetRootCertificateFromString method helps to add one or more root certificates into Resty client//// client.SetRootCertificateFromString("pem file content")func ( *Client) ( string) *Client {, := .tlsConfig()if != nil {.log.Errorf("%v", )return}if .RootCAs == nil {.RootCAs = x509.NewCertPool()}.RootCAs.AppendCertsFromPEM([]byte())return}// SetOutputDirectory method sets output directory for saving HTTP response into file.// If the output directory not exists then resty creates one. This setting is optional one,// if you're planning using absolute path in `Request.SetOutput` and can used together.//// client.SetOutputDirectory("/save/http/response/here")func ( *Client) ( string) *Client {.outputDirectory =return}// SetRateLimiter sets an optional `RateLimiter`. If set the rate limiter will control// all requests made with this client.//// Since v2.9.0func ( *Client) ( RateLimiter) *Client {.rateLimiter =return}// SetTransport method sets custom `*http.Transport` or any `http.RoundTripper`// compatible interface implementation in the resty client.//// Note://// - If transport is not type of `*http.Transport` then you may not be able to// take advantage of some of the Resty client settings.//// - It overwrites the Resty client transport instance and it's configurations.//// transport := &http.Transport{// // something like Proxying to httptest.Server, etc...// Proxy: func(req *http.Request) (*url.URL, error) {// return url.Parse(server.URL)// },// }//// client.SetTransport(transport)func ( *Client) ( http.RoundTripper) *Client {if != nil {.httpClient.Transport =}return}// SetScheme method sets custom scheme in the Resty client. It's way to override default.//// client.SetScheme("http")func ( *Client) ( string) *Client {if !IsStringEmpty() {.scheme = strings.TrimSpace()}return}// SetCloseConnection method sets variable `Close` in http request struct with the given// value. More info: https://golang.org/src/net/http/request.gofunc ( *Client) ( bool) *Client {.closeConnection =return}// SetDoNotParseResponse method instructs `Resty` not to parse the response body automatically.// Resty exposes the raw response body as `io.ReadCloser`. Also do not forget to close the body,// otherwise you might get into connection leaks, no connection reuse.//// Note: Response middlewares are not applicable, if you use this option. Basically you have// taken over the control of response parsing from `Resty`.func ( *Client) ( bool) *Client {.notParseResponse =return}// SetPathParam method sets single URL path key-value pair in the// Resty client instance.//// client.SetPathParam("userId", "sample@sample.com")//// Result:// URL - /v1/users/{userId}/details// Composed URL - /v1/users/sample@sample.com/details//// It replaces the value of the key while composing the request URL.// The value will be escaped using `url.PathEscape` function.//// Also it can be overridden at request level Path Params options,// see `Request.SetPathParam` or `Request.SetPathParams`.func ( *Client) (, string) *Client {.PathParams[] =return}// SetPathParams method sets multiple URL path key-value pairs at one go in the// Resty client instance.//// client.SetPathParams(map[string]string{// "userId": "sample@sample.com",// "subAccountId": "100002",// "path": "groups/developers",// })//// Result:// URL - /v1/users/{userId}/{subAccountId}/{path}/details// Composed URL - /v1/users/sample@sample.com/100002/groups%2Fdevelopers/details//// It replaces the value of the key while composing the request URL.// The values will be escaped using `url.PathEscape` function.//// Also it can be overridden at request level Path Params options,// see `Request.SetPathParam` or `Request.SetPathParams`.func ( *Client) ( map[string]string) *Client {for , := range {.SetPathParam(, )}return}// SetRawPathParam method sets single URL path key-value pair in the// Resty client instance.//// client.SetPathParam("userId", "sample@sample.com")//// Result:// URL - /v1/users/{userId}/details// Composed URL - /v1/users/sample@sample.com/details//// client.SetPathParam("path", "groups/developers")//// Result:// URL - /v1/users/{userId}/details// Composed URL - /v1/users/groups%2Fdevelopers/details//// It replaces the value of the key while composing the request URL.// The value will be used as it is and will not be escaped.//// Also it can be overridden at request level Path Params options,// see `Request.SetPathParam` or `Request.SetPathParams`.//// Since v2.8.0func ( *Client) (, string) *Client {.RawPathParams[] =return}// SetRawPathParams method sets multiple URL path key-value pairs at one go in the// Resty client instance.//// client.SetPathParams(map[string]string{// "userId": "sample@sample.com",// "subAccountId": "100002",// "path": "groups/developers",// })//// Result:// URL - /v1/users/{userId}/{subAccountId}/{path}/details// Composed URL - /v1/users/sample@sample.com/100002/groups/developers/details//// It replaces the value of the key while composing the request URL.// The values will be used as they are and will not be escaped.//// Also it can be overridden at request level Path Params options,// see `Request.SetPathParam` or `Request.SetPathParams`.//// Since v2.8.0func ( *Client) ( map[string]string) *Client {for , := range {.SetRawPathParam(, )}return}// SetJSONEscapeHTML method is to enable/disable the HTML escape on JSON marshal.//// Note: This option only applicable to standard JSON Marshaller.func ( *Client) ( bool) *Client {.jsonEscapeHTML =return}// EnableTrace method enables the Resty client trace for the requests fired from// the client using `httptrace.ClientTrace` and provides insights.//// client := resty.New().EnableTrace()//// resp, err := client.R().Get("https://httpbin.org/get")// fmt.Println("Error:", err)// fmt.Println("Trace Info:", resp.Request.TraceInfo())//// Also `Request.EnableTrace` available too to get trace info for single request.//// Since v2.0.0func ( *Client) () *Client {.trace = truereturn}// DisableTrace method disables the Resty client trace. Refer to `Client.EnableTrace`.//// Since v2.0.0func ( *Client) () *Client {.trace = falsereturn}// IsProxySet method returns the true is proxy is set from resty client otherwise// false. By default proxy is set from environment, refer to `http.ProxyFromEnvironment`.func ( *Client) () bool {return .proxyURL != nil}// GetClient method returns the current `http.Client` used by the resty client.func ( *Client) () *http.Client {return .httpClient}//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾// Client Unexported methods//_______________________________________________________________________// Executes method executes the given `Request` object and returns response// error.func ( *Client) ( *Request) (*Response, error) {// Lock the user-defined pre-request hooks..udBeforeRequestLock.RLock()defer .udBeforeRequestLock.RUnlock()// Lock the post-request hooks..afterResponseLock.RLock()defer .afterResponseLock.RUnlock()// Apply Request middlewarevar error// user defined on before request methods// to modify the *resty.Request objectfor , := range .udBeforeRequest {if = (, ); != nil {return nil, wrapNoRetryErr()}}// If there is a rate limiter set for this client, the Execute call// will return an error if the rate limit is exceeded.if .client.rateLimiter != nil {if !.client.rateLimiter.Allow() {return nil, wrapNoRetryErr(ErrRateLimitExceeded)}}// resty middlewaresfor , := range .beforeRequest {if = (, ); != nil {return nil, wrapNoRetryErr()}}if := .Header.Get("Host"); != "" {.RawRequest.Host =}// call pre-request if definedif .preReqHook != nil {if = .preReqHook(, .RawRequest); != nil {return nil, wrapNoRetryErr()}}if = requestLogger(, ); != nil {return nil, wrapNoRetryErr()}.RawRequest.Body = newRequestBodyReleaser(.RawRequest.Body, .bodyBuf).Time = time.Now(), := .httpClient.Do(.RawRequest):= &Response{Request: ,RawResponse: ,}if != nil || .notParseResponse || .notParseResponse {.setReceivedAt()return ,}if !.isSaveResponse {defer closeq(.Body):= .Body// GitHub #142 & #187if strings.EqualFold(.Header.Get(hdrContentEncodingKey), "gzip") && .ContentLength != 0 {if , := .(*gzip.Reader); ! {, = gzip.NewReader()if != nil {.setReceivedAt()return ,}defer closeq()}}if .body, = io.ReadAll(); != nil {.setReceivedAt()return ,}.size = int64(len(.body))}.setReceivedAt() // after we read the body// Apply Response middlewarefor , := range .afterResponse {if = (, ); != nil {break}}return , wrapNoRetryErr()}// getting TLS client config if not exists then create onefunc ( *Client) () (*tls.Config, error) {, := .Transport()if != nil {return nil,}if .TLSClientConfig == nil {.TLSClientConfig = &tls.Config{}}return .TLSClientConfig, nil}// Transport method returns `*http.Transport` currently in use or error// in case currently used `transport` is not a `*http.Transport`.//// Since v2.8.0 become exported method.func ( *Client) () (*http.Transport, error) {if , := .httpClient.Transport.(*http.Transport); {return , nil}return nil, errors.New("current transport is not an *http.Transport instance")}// just an internal helper methodfunc ( *Client) ( io.Writer) *Client {.log.(*logger).l.SetOutput()return}// ResponseError is a wrapper for including the server response with an error.// Neither the err nor the response should be nil.type ResponseError struct {Response *ResponseErr error}func ( *ResponseError) () string {return .Err.Error()}func ( *ResponseError) () error {return .Err}// Helper to run errorHooks hooks.// It wraps the error in a ResponseError if the resp is not nil// so hooks can access it.func ( *Client) ( *Request, *Response, error) {if != nil {if != nil { // wrap with ResponseError= &ResponseError{Response: , Err: }}for , := range .errorHooks {(, )}} else {for , := range .successHooks {(, )}}}// Helper to run panicHooks hooks.func ( *Client) ( *Request, error) {for , := range .panicHooks {(, )}}// Helper to run invalidHooks hooks.func ( *Client) ( *Request, error) {for , := range .invalidHooks {(, )}}//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾// File struct and its methods//_______________________________________________________________________// File struct represent file information for multipart requesttype File struct {Name stringParamName stringio.Reader}// String returns string value of current file detailsfunc ( *File) () string {return fmt.Sprintf("ParamName: %v; FileName: %v", .ParamName, .Name)}//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾// MultipartField struct//_______________________________________________________________________// MultipartField struct represent custom data part for multipart requesttype MultipartField struct {Param stringFileName stringContentType stringio.Reader}//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾// Unexported package methods//_______________________________________________________________________func createClient( *http.Client) *Client {if .Transport == nil {.Transport = createTransport(nil)}:= &Client{ // not setting lang default valuesQueryParam: url.Values{},FormData: url.Values{},Header: http.Header{},Cookies: make([]*http.Cookie, 0),RetryWaitTime: defaultWaitTime,RetryMaxWaitTime: defaultMaxWaitTime,PathParams: make(map[string]string),RawPathParams: make(map[string]string),JSONMarshal: json.Marshal,JSONUnmarshal: json.Unmarshal,XMLMarshal: xml.Marshal,XMLUnmarshal: xml.Unmarshal,HeaderAuthorizationKey: http.CanonicalHeaderKey("Authorization"),jsonEscapeHTML: true,httpClient: ,debugBodySizeLimit: math.MaxInt32,}// Logger.SetLogger(createLogger())// default before request middlewares.beforeRequest = []RequestMiddleware{parseRequestURL,parseRequestHeader,parseRequestBody,createHTTPRequest,addCredentials,}// user defined request middlewares.udBeforeRequest = []RequestMiddleware{}// default after response middlewares.afterResponse = []ResponseMiddleware{responseLogger,parseResponseBody,saveResponseIntoFile,}return}
![]() |
The pages are generated with Golds v0.6.7. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |