Repository: go-resty/resty
Pull request #867 (2024-09-23 04:44:34)

Refactor and streamline v3 codebase 


Patch:
diff --git a/client.go b/client.go
index 294fcea..fcd0e1d 100644
--- a/client.go
+++ b/client.go
@@ -15,7 +15,6 @@ import (
 	"net/url"
 	"os"
 	"reflect"
-	"regexp"
 	"strings"
 	"sync"
 	"time"
@@ -42,6 +41,12 @@ const (
 
 	// MethodOptions HTTP method
 	MethodOptions = "OPTIONS"
+
+	// MethodTrace HTTP method
+	MethodTrace = "TRACE"
+
+	// MethodConnect HTTP method
+	MethodConnect = "CONNECT"
 )
 
 var (
@@ -61,9 +66,6 @@ var (
 	jsonKey = "json"
 	xmlKey  = "xml"
 
-	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() any { return &bytes.Buffer{} }}
 )
@@ -159,7 +161,7 @@ type Client struct {
 	rawPathParams          map[string]string
 	header                 http.Header
 	userInfo               *User
-	token                  string
+	authToken              string
 	authScheme             string
 	cookies                []*http.Cookie
 	errorType              reflect.Type
@@ -173,18 +175,14 @@ type Client struct {
 	retryHooks             []OnRetryFunc
 	retryAfter             RetryAfterFunc
 	retryResetReaders      bool
-	jsonMarshal            func(v any) ([]byte, error)
-	jsonUnmarshal          func(data []byte, v any) error
-	xmlMarshal             func(v any) ([]byte, error)
-	xmlUnmarshal           func(data []byte, v any) error
 	headerAuthorizationKey string
 	responseBodyLimit      int64
 	jsonEscapeHTML         bool
 	setContentLength       bool
 	closeConnection        bool
 	notParseResponse       bool
-	trace                  bool
-	debugBodySizeLimit     int
+	isTrace                bool
+	debugBodyLimit         int
 	outputDirectory        string
 	scheme                 string
 	log                    Logger
@@ -299,6 +297,11 @@ func (c *Client) SetHeaderVerbatim(header, value string) *Client {
 	return c
 }
 
+// CookieJar method returns the HTTP cookie jar instance from the underlying Go HTTP Client.
+func (c *Client) CookieJar() http.CookieJar {
+	return c.Client().Jar
+}
+
 // SetCookieJar method sets custom [http.CookieJar] in the resty client. It's a way to override the default.
 //
 // For Example, sometimes we don't want to save cookies in API mode so that we can remove the default
@@ -306,7 +309,7 @@ func (c *Client) SetHeaderVerbatim(header, value string) *Client {
 //
 //	client.SetCookieJar(nil)
 func (c *Client) SetCookieJar(jar http.CookieJar) *Client {
-	c.GetClient().Jar = jar
+	c.Client().Jar = jar
 	return c
 }
 
@@ -458,11 +461,11 @@ func (c *Client) SetBasicAuth(username, password string) *Client {
 	return c
 }
 
-// Token method returns the auth token value registered in the client instance.
-func (c *Client) Token() string {
+// AuthToken method returns the auth token value registered in the client instance.
+func (c *Client) AuthToken() string {
 	c.lock.RLock()
 	defer c.lock.RUnlock()
-	return c.token
+	return c.authToken
 }
 
 // HeaderAuthorizationKey method returns the HTTP header name for Authorization from the client instance.
@@ -488,7 +491,7 @@ func (c *Client) HeaderAuthorizationKey() string {
 func (c *Client) SetAuthToken(token string) *Client {
 	c.lock.Lock()
 	defer c.lock.Unlock()
-	c.token = token
+	c.authToken = token
 	return c
 }
 
@@ -560,22 +563,24 @@ func (c *Client) R() *Request {
 	c.lock.RLock()
 	defer c.lock.RUnlock()
 	r := &Request{
-		QueryParams:       url.Values{},
-		FormData:          url.Values{},
-		Header:            http.Header{},
-		Cookies:           make([]*http.Cookie, 0),
-		PathParams:        make(map[string]string),
-		RawPathParams:     make(map[string]string),
-		Debug:             c.debug,
-		AuthScheme:        c.authScheme,
-		Token:             c.token,
-		UserInfo:          c.userInfo,
-		RetryCount:        c.retryCount,
-		RetryWaitTime:     c.retryWaitTime,
-		RetryMaxWaitTime:  c.retryMaxWaitTime,
-		RetryResetReaders: c.retryResetReaders,
-		CloseConnection:   c.closeConnection,
-		NotParseResponse:  c.notParseResponse,
+		QueryParams:        url.Values{},
+		FormData:           url.Values{},
+		Header:             http.Header{},
+		Cookies:            make([]*http.Cookie, 0),
+		PathParams:         make(map[string]string),
+		RawPathParams:      make(map[string]string),
+		Debug:              c.debug,
+		AuthScheme:         c.authScheme,
+		AuthToken:          c.authToken,
+		UserInfo:           c.userInfo,
+		RetryCount:         c.retryCount,
+		RetryWaitTime:      c.retryWaitTime,
+		RetryMaxWaitTime:   c.retryMaxWaitTime,
+		RetryResetReaders:  c.retryResetReaders,
+		CloseConnection:    c.closeConnection,
+		DoNotParseResponse: c.notParseResponse,
+		DebugBodyLimit:     c.debugBodyLimit,
+		ResponseBodyLimit:  c.responseBodyLimit,
 
 		client:              c,
 		multipartFiles:      []*File{},
@@ -583,13 +588,10 @@ func (c *Client) R() *Request {
 		jsonEscapeHTML:      c.jsonEscapeHTML,
 		log:                 c.log,
 		setContentLength:    c.setContentLength,
-		trace:               c.trace,
-		debugBodySizeLimit:  c.debugBodySizeLimit,
-		responseBodyLimit:   c.responseBodyLimit,
+		IsTrace:             c.isTrace,
 		generateCurlOnDebug: c.generateCurlOnDebug,
 	}
 
-	r.retryConditions = append(r.retryConditions, c.retryConditions...)
 	return r
 }
 
@@ -772,8 +774,8 @@ func (c *Client) inferContentTypeDecoder(ct ...string) (ContentTypeDecoder, bool
 	return nil, false
 }
 
-// Debug method returns `true` if the client is in debug mode; otherwise, it is `false`.
-func (c *Client) Debug() bool {
+// IsDebug method returns `true` if the client is in debug mode; otherwise, it is `false`.
+func (c *Client) IsDebug() bool {
 	c.lock.RLock()
 	defer c.lock.RUnlock()
 	return c.debug
@@ -796,6 +798,13 @@ func (c *Client) SetDebug(d bool) *Client {
 	return c
 }
 
+// DebugBodyLimit method returns the debug body limit value set on the client instance
+func (c *Client) DebugBodyLimit() int {
+	c.lock.RLock()
+	defer c.lock.RUnlock()
+	return c.debugBodyLimit
+}
+
 // SetDebugBodyLimit sets the maximum size in bytes for which the response and
 // request body will be logged in debug mode.
 //
@@ -803,7 +812,7 @@ func (c *Client) SetDebug(d bool) *Client {
 func (c *Client) SetDebugBodyLimit(sl int) *Client {
 	c.lock.Lock()
 	defer c.lock.Unlock()
-	c.debugBodySizeLimit = sl
+	c.debugBodyLimit = sl
 	return c
 }
 
@@ -833,8 +842,8 @@ func (c *Client) OnResponseLog(rl ResponseLogCallback) *Client {
 	return c
 }
 
-// DisableWarn method returns `true` if the warning message is disabled; otherwise, it is `false`.
-func (c *Client) DisableWarn() bool {
+// IsDisableWarn method returns `true` if the warning message is disabled; otherwise, it is `false`.
+func (c *Client) IsDisableWarn() bool {
 	c.lock.RLock()
 	defer c.lock.RUnlock()
 	return c.disableWarn
@@ -872,6 +881,13 @@ func (c *Client) SetAllowGetMethodPayload(a bool) *Client {
 	return c
 }
 
+// Logger method returns the logger instance used by the client instance.
+func (c *Client) Logger() Logger {
+	c.lock.RLock()
+	defer c.lock.RUnlock()
+	return c.log
+}
+
 // SetLogger method sets given writer for logging Resty request and response details.
 //
 // Compliant to interface [resty.Logger]
@@ -882,6 +898,13 @@ func (c *Client) SetLogger(l Logger) *Client {
 	return c
 }
 
+// IsContentLength method returns true if the user requests to set content length. Otherwise, it is false.
+func (c *Client) IsContentLength() bool {
+	c.lock.RLock()
+	defer c.lock.RUnlock()
+	return c.setContentLength
+}
+
 // SetContentLength method enables the HTTP header `Content-Length` value for every request.
 // By default, Resty won't set `Content-Length`.
 //
@@ -1031,42 +1054,6 @@ func (c *Client) SetRetryAfter(callback RetryAfterFunc) *Client {
 	return c
 }
 
-// SetJSONMarshaler method sets the JSON marshaler function to marshal the request body.
-// By default, Resty uses [encoding/json] package to marshal the request body.
-func (c *Client) SetJSONMarshaler(marshaler func(v any) ([]byte, error)) *Client {
-	c.lock.Lock()
-	defer c.lock.Unlock()
-	c.jsonMarshal = marshaler
-	return c
-}
-
-// SetJSONUnmarshaler method sets the JSON unmarshaler function to unmarshal the response body.
-// By default, Resty uses [encoding/json] package to unmarshal the response body.
-func (c *Client) SetJSONUnmarshaler(unmarshaler func(data []byte, v any) error) *Client {
-	c.lock.Lock()
-	defer c.lock.Unlock()
-	c.jsonUnmarshal = unmarshaler
-	return c
-}
-
-// SetXMLMarshaler method sets the XML marshaler function to marshal the request body.
-// By default, Resty uses [encoding/xml] package to marshal the request body.
-func (c *Client) SetXMLMarshaler(marshaler func(v any) ([]byte, error)) *Client {
-	c.lock.Lock()
-	defer c.lock.Unlock()
-	c.xmlMarshal = marshaler
-	return c
-}
-
-// SetXMLUnmarshaler method sets the XML unmarshaler function to unmarshal the response body.
-// By default, Resty uses [encoding/xml] package to unmarshal the response body.
-func (c *Client) SetXMLUnmarshaler(unmarshaler func(data []byte, v any) error) *Client {
-	c.lock.Lock()
-	defer c.lock.Unlock()
-	c.xmlUnmarshal = unmarshaler
-	return c
-}
-
 // RetryConditions method returns all the retry condition functions.
 func (c *Client) RetryConditions() []RetryConditionFunc {
 	c.lock.RLock()
@@ -1291,7 +1278,7 @@ func (c *Client) OutputDirectory() string {
 
 // SetOutputDirectory method sets the output directory for saving HTTP responses in a file.
 // Resty creates one if the output directory does not exist. This setting is optional,
-// if you plan to use the absolute path in [Request.SetOutput] and can used together.
+// if you plan to use the absolute path in [Request.SetOutputFile] and can used together.
 //
 //	client.SetOutputDirectory("/save/http/response/here")
 func (c *Client) SetOutputDirectory(dirPath string) *Client {
@@ -1317,6 +1304,21 @@ func (c *Client) SetRateLimiter(rl RateLimiter) *Client {
 	return c
 }
 
+var ErrNotHttpTransportType = errors.New("resty: not a http.Transport type")
+
+// Transport method returns [http.Transport] currently in use or error
+// in case the currently used `transport` is not a [http.Transport].
+//
+// Since v2.8.0 has become exported method.
+func (c *Client) Transport() (*http.Transport, error) {
+	c.lock.RLock()
+	defer c.lock.RUnlock()
+	if transport, ok := c.httpClient.Transport.(*http.Transport); ok {
+		return transport, nil
+	}
+	return nil, ErrNotHttpTransportType
+}
+
 // SetTransport method sets custom [http.Transport] or any [http.RoundTripper]
 // compatible interface implementation in the Resty client.
 //
@@ -1356,7 +1358,7 @@ func (c *Client) Scheme() string {
 func (c *Client) SetScheme(scheme string) *Client {
 	c.lock.Lock()
 	defer c.lock.Unlock()
-	if !IsStringEmpty(scheme) {
+	if !isStringEmpty(scheme) {
 		c.scheme = strings.TrimSpace(scheme)
 	}
 	return c
@@ -1529,7 +1531,7 @@ func (c *Client) ResponseBodyLimit() int64 {
 // in the uncompressed response is larger than the limit.
 // Body size limit will not be enforced in the following cases:
 //   - ResponseBodyLimit <= 0, which is the default behavior.
-//   - [Request.SetOutput] is called to save response data to the file.
+//   - [Request.SetOutputFile] is called to save response data to the file.
 //   - "DoNotParseResponse" is set for client or request.
 //
 // It can be overridden at the request level; see [Request.SetResponseBodyLimit]
@@ -1551,17 +1553,31 @@ func (c *Client) SetResponseBodyLimit(v int64) *Client {
 //
 // The method [Request.EnableTrace] is also available to get trace info for a single request.
 func (c *Client) EnableTrace() *Client {
-	c.lock.Lock()
-	defer c.lock.Unlock()
-	c.trace = true
+	c.SetTrace(true)
 	return c
 }
 
 // DisableTrace method disables the Resty client trace. Refer to [Client.EnableTrace].
 func (c *Client) DisableTrace() *Client {
+	c.SetTrace(false)
+	return c
+}
+
+// IsTrace method returns true if the trace is enabled on the client instance; otherwise, it returns false.
+func (c *Client) IsTrace() bool {
+	c.lock.RLock()
+	defer c.lock.RUnlock()
+	return c.isTrace
+}
+
+// SetTrace method is used to turn on/off the trace capability in the Resty client
+// Refer to [Client.EnableTrace] or [Client.DisableTrace].
+//
+// Also, see [Request.SetTrace]
+func (c *Client) SetTrace(t bool) *Client {
 	c.lock.Lock()
 	defer c.lock.Unlock()
-	c.trace = false
+	c.isTrace = t
 	return c
 }
 
@@ -1572,13 +1588,24 @@ func (c *Client) DisableTrace() *Client {
 //   - Potential to leak sensitive data from [Request] and [Response] in the debug log.
 //   - Beware of memory usage since the request body is reread.
 func (c *Client) EnableGenerateCurlOnDebug() *Client {
-	c.generateCurlOnDebug = true
+	c.SetGenerateCurlOnDebug(true)
 	return c
 }
 
 // DisableGenerateCurlOnDebug method disables the option set by [Client.EnableGenerateCurlOnDebug].
 func (c *Client) DisableGenerateCurlOnDebug() *Client {
-	c.generateCurlOnDebug = false
+	c.SetGenerateCurlOnDebug(false)
+	return c
+}
+
+// SetGenerateCurlOnDebug method is used to turn on/off the generate CURL command in debug mode
+// at the client instance level.
+//
+// It can be overridden at the request level; see [Request.SetGenerateCurlOnDebug]
+func (c *Client) SetGenerateCurlOnDebug(b bool) *Client {
+	c.lock.Lock()
+	defer c.lock.Unlock()
+	c.generateCurlOnDebug = b
 	return c
 }
 
@@ -1588,26 +1615,13 @@ func (c *Client) IsProxySet() bool {
 	return c.ProxyURL() != nil
 }
 
-// GetClient method returns the underlying [http.Client] used by the Resty.
-func (c *Client) GetClient() *http.Client {
+// Client method returns the underlying Go [http.Client] used by the Resty.
+func (c *Client) Client() *http.Client {
 	c.lock.RLock()
 	defer c.lock.RUnlock()
 	return c.httpClient
 }
 
-// Transport method returns [http.Transport] currently in use or error
-// in case the currently used `transport` is not a [http.Transport].
-//
-// Since v2.8.0 has become exported method.
-func (c *Client) Transport() (*http.Transport, error) {
-	c.lock.RLock()
-	defer c.lock.RUnlock()
-	if transport, ok := c.httpClient.Transport.(*http.Transport); ok {
-		return transport, nil
-	}
-	return nil, errors.New("current transport is not an *http.Transport instance")
-}
-
 // Clone method returns a clone of the original client.
 //
 // NOTE: Use with care:
@@ -1640,7 +1654,7 @@ func (c *Client) executeBefore(req *Request) error {
 	// will return an error if the rate limit is exceeded.
 	if req.client.RateLimiter() != nil {
 		if !req.client.RateLimiter().Allow() {
-			return wrapNoRetryErr(ErrRateLimitExceeded)
+			return ErrRateLimitExceeded
 		}
 	}
 
@@ -1678,7 +1692,7 @@ func (c *Client) execute(req *Request) (*Response, error) {
 	}
 
 	req.Time = time.Now()
-	resp, err := c.GetClient().Do(req.RawRequest)
+	resp, err := c.Client().Do(req.RawRequest)
 
 	response := &Response{
 		Request:     req,
@@ -1689,14 +1703,14 @@ func (c *Client) execute(req *Request) (*Response, error) {
 	if resp != nil {
 		response.Body = &limitReadCloser{
 			r: resp.Body,
-			l: req.responseBodyLimit,
+			l: req.ResponseBodyLimit,
 			f: func(s int64) {
 				response.size = s
 			},
 		}
 	}
 
-	if err != nil || req.NotParseResponse { // error or do not parse response
+	if err != nil || req.DoNotParseResponse { // error or do not parse response
 		return response, wrapErrors(responseLogger(c, response), err)
 	}
 
diff --git a/middleware.go b/middleware.go
index 13efc1e..2f16bae 100644
--- a/middleware.go
+++ b/middleware.go
@@ -141,7 +141,7 @@ func parseRequestURL(c *Client, r *Request) error {
 		// standard package `url.Encode(...)` sorts the query params
 		// alphabetically
 		if len(r.QueryParams) > 0 {
-			if IsStringEmpty(reqURL.RawQuery) {
+			if isStringEmpty(reqURL.RawQuery) {
 				reqURL.RawQuery = r.QueryParams.Encode()
 			} else {
 				reqURL.RawQuery = reqURL.RawQuery + "&" + r.QueryParams.Encode()
@@ -162,11 +162,11 @@ func parseRequestHeader(c *Client, r *Request) error {
 		r.Header[k] = v[:]
 	}
 
-	if IsStringEmpty(r.Header.Get(hdrUserAgentKey)) {
+	if isStringEmpty(r.Header.Get(hdrUserAgentKey)) {
 		r.Header.Set(hdrUserAgentKey, hdrUserAgentValue)
 	}
 
-	if ct := r.Header.Get(hdrContentTypeKey); IsStringEmpty(r.Header.Get(hdrAcceptKey)) && !IsStringEmpty(ct) && (IsJSONType(ct) || IsXMLType(ct)) {
+	if ct := r.Header.Get(hdrContentTypeKey); isStringEmpty(r.Header.Get(hdrAcceptKey)) && !isStringEmpty(ct) && (isJSONContentType(ct) || isXMLContentType(ct)) {
 		r.Header.Set(hdrAcceptKey, r.Header.Get(hdrContentTypeKey))
 	}
 
@@ -237,7 +237,7 @@ func createHTTPRequest(c *Client, r *Request) (err error) {
 	}
 
 	// Enable trace
-	if r.trace {
+	if r.IsTrace {
 		r.clientTrace = &clientTrace{}
 		r.ctx = r.clientTrace.createContext(r.Context())
 	}
@@ -271,21 +271,21 @@ func addCredentials(c *Client, r *Request) error {
 		isBasicAuth = true
 	}
 
-	if !c.disableWarn {
+	if !c.IsDisableWarn() {
 		if isBasicAuth && !strings.HasPrefix(r.URL, "https") {
 			r.log.Warnf("Using Basic Auth in HTTP mode is not secure, use HTTPS")
 		}
 	}
 
 	// Build the token Auth header
-	if !IsStringEmpty(r.Token) {
+	if !isStringEmpty(r.AuthToken) {
 		var authScheme string
-		if IsStringEmpty(r.AuthScheme) {
+		if isStringEmpty(r.AuthScheme) {
 			authScheme = "Bearer"
 		} else {
 			authScheme = r.AuthScheme
 		}
-		r.RawRequest.Header.Set(c.HeaderAuthorizationKey(), authScheme+" "+r.Token)
+		r.RawRequest.Header.Set(c.HeaderAuthorizationKey(), authScheme+" "+r.AuthToken)
 	}
 
 	return nil
@@ -296,7 +296,7 @@ func createCurlCmd(c *Client, r *Request) (err error) {
 		if r.resultCurlCmd == nil {
 			r.resultCurlCmd = new(string)
 		}
-		*r.resultCurlCmd = buildCurlRequest(r.RawRequest, c.GetClient().Jar)
+		*r.resultCurlCmd = buildCurlRequest(r.RawRequest, c.Client().Jar)
 	}
 	return nil
 }
@@ -304,9 +304,9 @@ func createCurlCmd(c *Client, r *Request) (err error) {
 func requestLogger(c *Client, r *Request) error {
 	if r.Debug {
 		rr := r.RawRequest
-		rh := copyHeaders(rr.Header)
-		if c.GetClient().Jar != nil {
-			for _, cookie := range c.GetClient().Jar.Cookies(r.RawRequest.URL) {
+		rh := rr.Header.Clone()
+		if c.Client().Jar != nil {
+			for _, cookie := range c.Client().Jar.Cookies(r.RawRequest.URL) {
 				s := fmt.Sprintf("%s=%s", cookie.Name, cookie.Value)
 				if c := rh.Get("Cookie"); c != "" {
 					rh.Set("Cookie", c+"; "+s)
@@ -315,7 +315,7 @@ func requestLogger(c *Client, r *Request) error {
 				}
 			}
 		}
-		rl := &RequestLog{Header: rh, Body: r.fmtBodyString(r.debugBodySizeLimit)}
+		rl := &RequestLog{Header: rh, Body: r.fmtBodyString(r.DebugBodyLimit)}
 		if c.requestLog != nil {
 			if err := c.requestLog(rl); err != nil {
 				return err
@@ -332,7 +332,7 @@ func requestLogger(c *Client, r *Request) error {
 		reqLog += "~~~ REQUEST ~~~\n" +
 			fmt.Sprintf("%s  %s  %s\n", r.Method, rr.URL.RequestURI(), rr.Proto) +
 			fmt.Sprintf("HOST   : %s\n", rr.URL.Host) +
-			fmt.Sprintf("HEADERS:\n%s\n", composeHeaders(c, r, rl.Header)) +
+			fmt.Sprintf("HEADERS:\n%s\n", composeHeaders(rl.Header)) +
 			fmt.Sprintf("BODY   :\n%v\n", rl.Body) +
 			"------------------------------------------------------------------------------\n"
 
@@ -349,7 +349,7 @@ func requestLogger(c *Client, r *Request) error {
 
 func responseLogger(c *Client, res *Response) error {
 	if res.Request.Debug {
-		rl := &ResponseLog{Header: copyHeaders(res.Header()), Body: res.fmtBodyString(res.Request.debugBodySizeLimit)}
+		rl := &ResponseLog{Header: res.Header().Clone(), Body: res.fmtBodyString(res.Request.DebugBodyLimit)}
 		if c.responseLog != nil {
 			c.lock.RLock()
 			defer c.lock.RUnlock()
@@ -365,7 +365,7 @@ func responseLogger(c *Client, res *Response) error {
 			fmt.Sprintf("RECEIVED AT  : %v\n", res.ReceivedAt().Format(time.RFC3339Nano)) +
 			fmt.Sprintf("TIME DURATION: %v\n", res.Time()) +
 			"HEADERS      :\n" +
-			composeHeaders(c, res.Request, rl.Header) + "\n"
+			composeHeaders(rl.Header) + "\n"
 		if res.Request.isSaveResponse {
 			debugLog += "BODY         :\n***** RESPONSE WRITTEN INTO FILE *****\n"
 		} else {
@@ -392,9 +392,9 @@ func parseResponseBody(c *Client, res *Response) (err error) {
 	// TODO Attention Required when working on Compression
 
 	rct := firstNonEmpty(
-		res.Request.forceContentType,
+		res.Request.ForceResponseContentType,
 		res.Header().Get(hdrContentTypeKey),
-		res.Request.fallbackContentType,
+		res.Request.ExpectResponseContentType,
 	)
 	decKey := inferContentTypeMapKey(rct)
 	decFunc, found := c.inferContentTypeDecoder(rct, decKey)
@@ -500,9 +500,9 @@ var ErrUnsupportedRequestBodyKind = errors.New("resty: unsupported request body
 
 func handleRequestBody(c *Client, r *Request) error {
 	contentType := r.Header.Get(hdrContentTypeKey)
-	if IsStringEmpty(contentType) {
+	if isStringEmpty(contentType) {
 		// it is highly recommended that the user provide a request content-type
-		contentType = DetectContentType(r.Body)
+		contentType = detectContentType(r.Body)
 		r.Header.Set(hdrContentTypeKey, contentType)
 	}
 
@@ -559,11 +559,11 @@ func saveResponseIntoFile(c *Client, res *Response) error {
 	if res.Request.isSaveResponse {
 		file := ""
 
-		if len(c.OutputDirectory()) > 0 && !filepath.IsAbs(res.Request.outputFile) {
+		if len(c.OutputDirectory()) > 0 && !filepath.IsAbs(res.Request.OutputFile) {
 			file += c.OutputDirectory() + string(filepath.Separator)
 		}
 
-		file = filepath.Clean(file + res.Request.outputFile)
+		file = filepath.Clean(file + res.Request.OutputFile)
 		if err := createDirectory(filepath.Dir(file)); err != nil {
 			return err
 		}
diff --git a/request.go b/request.go
index 7620eb7..491dc97 100644
--- a/request.go
+++ b/request.go
@@ -27,26 +27,32 @@ import (
 // Resty client. The [Request] provides an option to override client-level
 // settings and also an option for the request composition.
 type Request struct {
-	URL              string
-	Method           string
-	Token            string
-	AuthScheme       string
-	QueryParams      url.Values
-	FormData         url.Values
-	PathParams       map[string]string
-	RawPathParams    map[string]string
-	Header           http.Header
-	Time             time.Time
-	Body             any
-	Result           any
-	Error            any
-	RawRequest       *http.Request
-	SRV              *SRVRecord
-	UserInfo         *User
-	Cookies          []*http.Cookie
-	Debug            bool
-	CloseConnection  bool
-	NotParseResponse bool
+	URL                       string
+	Method                    string
+	AuthToken                 string
+	AuthScheme                string
+	QueryParams               url.Values
+	FormData                  url.Values
+	PathParams                map[string]string
+	RawPathParams             map[string]string
+	Header                    http.Header
+	Time                      time.Time
+	Body                      any
+	Result                    any
+	Error                     any
+	RawRequest                *http.Request
+	SRV                       *SRVRecord
+	UserInfo                  *User
+	Cookies                   []*http.Cookie
+	Debug                     bool
+	CloseConnection           bool
+	DoNotParseResponse        bool
+	OutputFile                string
+	ExpectResponseContentType string
+	ForceResponseContentType  string
+	DebugBodyLimit            int
+	ResponseBodyLimit         int64
+	IsTrace                   bool
 
 	// Retry
 	RetryCount        int
@@ -63,10 +69,6 @@ type Request struct {
 	setContentLength    bool
 	isSaveResponse      bool
 	jsonEscapeHTML      bool
-	trace               bool
-	outputFile          string
-	fallbackContentType string
-	forceContentType    string
 	ctx                 context.Context
 	values              map[string]any
 	client              *Client
@@ -77,8 +79,6 @@ type Request struct {
 	multipartFiles      []*File
 	multipartFields     []*MultipartField
 	retryConditions     []RetryConditionFunc
-	debugBodySizeLimit  int
-	responseBodyLimit   int64
 	resultCurlCmd       *string
 	generateCurlOnDebug bool
 }
@@ -532,8 +532,8 @@ func (r *Request) SetBasicAuth(username, password string) *Request {
 //	client.R().SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F")
 //
 // It overrides the Auth token set by method [Client.SetAuthToken].
-func (r *Request) SetAuthToken(token string) *Request {
-	r.Token = token
+func (r *Request) SetAuthToken(authToken string) *Request {
+	r.AuthToken = authToken
 	return r
 }
 
@@ -591,7 +591,7 @@ func (r *Request) SetDigestAuth(username, password string) *Request {
 	return r
 }
 
-// SetOutput method sets the output file for the current HTTP request. The current
+// SetOutputFile method sets the output file for the current HTTP request. The current
 // HTTP response will be saved in the given file. It is similar to the `curl -o` flag.
 //
 // Absolute path or relative path can be used.
@@ -600,14 +600,14 @@ func (r *Request) SetDigestAuth(username, password string) *Request {
 // in the [Client.SetOutputDirectory].
 //
 //	client.R().
-//		SetOutput("/Users/jeeva/Downloads/ReplyWithHeader-v5.1-beta.zip").
+//		SetOutputFile("/Users/jeeva/Downloads/ReplyWithHeader-v5.1-beta.zip").
 //		Get("http://bit.ly/1LouEKr")
 //
 // NOTE: In this scenario
 //   - [Response.BodyBytes] might be nil.
 //   - [Response].Body might be already read.
-func (r *Request) SetOutput(file string) *Request {
-	r.outputFile = file
+func (r *Request) SetOutputFile(file string) *Request {
+	r.OutputFile = file
 	r.isSaveResponse = true
 	return r
 }
@@ -640,7 +640,7 @@ func (r *Request) SetCloseConnection(close bool) *Request {
 // NOTE: [Response] middlewares are not executed using this option. You have
 // taken over the control of response parsing from Resty.
 func (r *Request) SetDoNotParseResponse(notParse bool) *Request {
-	r.NotParseResponse = notParse
+	r.DoNotParseResponse = notParse
 	return r
 }
 
@@ -651,12 +651,12 @@ func (r *Request) SetDoNotParseResponse(notParse bool) *Request {
 // in the uncompressed response is larger than the limit.
 // Body size limit will not be enforced in the following cases:
 //   - ResponseBodyLimit <= 0, which is the default behavior.
-//   - [Request.SetOutput] is called to save response data to the file.
+//   - [Request.SetOutputFile] is called to save response data to the file.
 //   - "DoNotParseResponse" is set for client or request.
 //
 // It overrides the value set at the client instance level, see [Client.SetResponseBodyLimit]
 func (r *Request) SetResponseBodyLimit(v int64) *Request {
-	r.responseBodyLimit = v
+	r.ResponseBodyLimit = v
 	return r
 }
 
@@ -756,21 +756,21 @@ func (r *Request) SetRawPathParams(params map[string]string) *Request {
 	return r
 }
 
-// ExpectContentType method allows to provide fallback `Content-Type` for automatic unmarshalling
-// when the `Content-Type` response header is unavailable.
-func (r *Request) ExpectContentType(contentType string) *Request {
-	r.fallbackContentType = contentType
+// SetExpectResponseContentType method allows to provide fallback `Content-Type`
+// for automatic unmarshalling when the `Content-Type` response header is unavailable.
+func (r *Request) SetExpectResponseContentType(contentType string) *Request {
+	r.ExpectResponseContentType = contentType
 	return r
 }
 
-// ForceContentType method provides a strong sense of response `Content-Type` for
+// SetForceResponseContentType method provides a strong sense of response `Content-Type` for
 // automatic unmarshalling. Resty gives this a higher priority than the `Content-Type`
 // response header.
 //
-// This means that if both [Request.ForceContentType] is set and
-// the response `Content-Type` is available, `ForceContentType` will win.
-func (r *Request) ForceContentType(contentType string) *Request {
-	r.forceContentType = contentType
+// This means that if both [Request.SetForceResponseContentType] is set and
+// the response `Content-Type` is available, `SetForceResponseContentType` value will win.
+func (r *Request) SetForceResponseContentType(contentType string) *Request {
+	r.ForceResponseContentType = contentType
 	return r
 }
 
@@ -900,9 +900,24 @@ func (r *Request) SetRetryResetReaders(b bool) *Request {
 //	fmt.Println("Error:", err)
 //	fmt.Println("Trace Info:", resp.Request.TraceInfo())
 //
-// See [Client.EnableTrace] is also available to get trace info for all requests.
+// See [Client.EnableTrace], [Client.SetTrace] are also available to
+// get trace info for all requests.
 func (r *Request) EnableTrace() *Request {
-	r.trace = true
+	r.SetTrace(true)
+	return r
+}
+
+// DisableTrace method disables the request trace for the current request
+func (r *Request) DisableTrace() *Request {
+	r.SetTrace(false)
+	return r
+}
+
+// SetTrace method is used to turn on/off the trace capability at the request level
+//
+// See [Request.EnableTrace] or [Client.SetTrace]
+func (r *Request) SetTrace(t bool) *Request {
+	r.IsTrace = t
 	return r
 }
 
@@ -913,14 +928,22 @@ func (r *Request) EnableTrace() *Request {
 //   - Potential to leak sensitive data from [Request] and [Response] in the debug log.
 //   - Beware of memory usage since the request body is reread.
 func (r *Request) EnableGenerateCurlOnDebug() *Request {
-	r.generateCurlOnDebug = true
+	r.SetGenerateCurlOnDebug(true)
 	return r
 }
 
 // DisableGenerateCurlOnDebug method disables the option set by [Request.EnableGenerateCurlOnDebug].
 // It overrides the options set by the [Client].
 func (r *Request) DisableGenerateCurlOnDebug() *Request {
-	r.generateCurlOnDebug = false
+	r.SetGenerateCurlOnDebug(false)
+	return r
+}
+
+// SetGenerateCurlOnDebug method is used to turn on/off the generate CURL command in debug mode.
+//
+// It overrides the options set by the [Client.SetGenerateCurlOnDebug]
+func (r *Request) SetGenerateCurlOnDebug(b bool) *Request {
+	r.generateCurlOnDebug = b
 	return r
 }
 
@@ -999,19 +1022,29 @@ func (r *Request) Put(url string) (*Response, error) {
 	return r.Execute(MethodPut, url)
 }
 
+// Patch method does PATCH HTTP request. It's defined in section 2 of RFC5789.
+func (r *Request) Patch(url string) (*Response, error) {
+	return r.Execute(MethodPatch, url)
+}
+
 // Delete method does DELETE HTTP request. It's defined in section 4.3.5 of RFC7231.
 func (r *Request) Delete(url string) (*Response, error) {
 	return r.Execute(MethodDelete, url)
 }
 
+// Connect method does CONNECT HTTP request. It's defined in section 4.3.6 of RFC7231.
+func (r *Request) Connect(url string) (*Response, error) {
+	return r.Execute(MethodConnect, url)
+}
+
 // Options method does OPTIONS HTTP request. It's defined in section 4.3.7 of RFC7231.
 func (r *Request) Options(url string) (*Response, error) {
 	return r.Execute(MethodOptions, url)
 }
 
-// Patch method does PATCH HTTP request. It's defined in section 2 of RFC5789.
-func (r *Request) Patch(url string) (*Response, error) {
-	return r.Execute(MethodPatch, url)
+// Trace method does TRACE HTTP request. It's defined in section 4.3.8 of RFC7231.
+func (r *Request) Trace(url string) (*Response, error) {
+	return r.Execute(MethodTrace, url)
 }
 
 // Send method performs the HTTP request using the method and URL already defined
@@ -1070,7 +1103,7 @@ func (r *Request) Execute(method, url string) (*Response, error) {
 		return resp, unwrapNoRetryErr(err)
 	}
 
-	err = Backoff(
+	err = backoff(
 		func() (*Response, error) {
 			r.Attempt++
 
@@ -1086,7 +1119,7 @@ func (r *Request) Execute(method, url string) (*Response, error) {
 		Retries(r.RetryCount),
 		WaitTime(r.RetryWaitTime),
 		MaxWaitTime(r.RetryMaxWaitTime),
-		RetryConditions(r.retryConditions),
+		RetryConditions(append(r.retryConditions, r.client.RetryConditions()...)),
 		RetryHooks(r.client.RetryHooks()),
 		ResetMultipartReaders(r.RetryResetReaders),
 	)
@@ -1210,29 +1243,34 @@ func (r *Request) fmtBodyString(sl int) (body string) {
 	var err error
 
 	contentType := r.Header.Get(hdrContentTypeKey)
+	ctKey := inferContentTypeMapKey(contentType)
+
 	kind := inferKind(r.Body)
-	if canJSONMarshal(contentType, kind) {
-		var bodyBuf *bytes.Buffer
-		bodyBuf, err = noescapeJSONMarshalIndent(&r.Body)
-		if err == nil {
-			prtBodyBytes = bodyBuf.Bytes()
-			defer releaseBuffer(bodyBuf)
+	if jsonKey == ctKey &&
+		(kind == reflect.Struct || kind == reflect.Map || kind == reflect.Slice) {
+		buf := acquireBuffer()
+		defer releaseBuffer(buf)
+		if err = encodeJSONEscapeHTMLIndent(buf, r.Body, false, "   "); err == nil {
+			prtBodyBytes = buf.Bytes()
 		}
-	} else if IsXMLType(contentType) && (kind == reflect.Struct) {
+	} else if xmlKey == ctKey && kind == reflect.Struct {
 		prtBodyBytes, err = xml.MarshalIndent(&r.Body, "", "   ")
-	} else if b, ok := r.Body.(string); ok {
-		if IsJSONType(contentType) {
-			bodyBytes := []byte(b)
-			out := acquireBuffer()
-			defer releaseBuffer(out)
-			if err = json.Indent(out, bodyBytes, "", "   "); err == nil {
-				prtBodyBytes = out.Bytes()
+	} else {
+		switch b := r.Body.(type) {
+		case string:
+			prtBodyBytes = []byte(b)
+			if jsonKey == ctKey {
+				prtBodyBytes = jsonIndent(prtBodyBytes)
 			}
-		} else {
-			body = b
+		case []byte:
+			body = fmt.Sprintf("***** BODY IS byte(s) (size - %d) *****", len(b))
+			return
 		}
-	} else if b, ok := r.Body.([]byte); ok {
-		body = fmt.Sprintf("***** BODY IS byte(s) (size - %d) *****", len(b))
+	}
+
+	bodySize := len(prtBodyBytes)
+	if bodySize > sl {
+		body = fmt.Sprintf("***** REQUEST TOO LARGE (size - %d) *****", bodySize)
 		return
 	}
 
@@ -1240,13 +1278,6 @@ func (r *Request) fmtBodyString(sl int) (body string) {
 		body = string(prtBodyBytes)
 	}
 
-	if len(body) > 0 {
-		bodySize := len([]byte(body))
-		if bodySize > sl {
-			body = fmt.Sprintf("***** REQUEST TOO LARGE (size - %d) *****", bodySize)
-		}
-	}
-
 	return
 }
 
@@ -1268,16 +1299,11 @@ func (r *Request) initValuesMap() {
 	}
 }
 
-var noescapeJSONMarshalIndent = func(v any) (*bytes.Buffer, error) {
+func jsonIndent(v []byte) []byte {
 	buf := acquireBuffer()
-	encoder := json.NewEncoder(buf)
-	encoder.SetEscapeHTML(false)
-	encoder.SetIndent("", "   ")
-
-	if err := encoder.Encode(v); err != nil {
-		releaseBuffer(buf)
-		return nil, err
+	defer releaseBuffer(buf)
+	if err := json.Indent(buf, v, "", "   "); err != nil {
+		return v
 	}
-
-	return buf, nil
+	return buf.Bytes()
 }
diff --git a/response.go b/response.go
index ddc3d91..ca11b1a 100644
--- a/response.go
+++ b/response.go
@@ -32,9 +32,9 @@ type Response struct {
 // BodyBytes method returns the HTTP response as `[]byte` slice for the executed request.
 //
 // NOTE:
-//   - [Response.BodyBytes] might be `nil` if [Request.SetOutput], [Request.SetDoNotParseResponse],
+//   - [Response.BodyBytes] might be `nil` if [Request.SetOutputFile], [Request.SetDoNotParseResponse],
 //     [Client.SetDoNotParseResponse] method is used.
-//   - [Response.BodyBytes] might be `nil` if [Response].Body is already read.
+//   - [Response.BodyBytes] might be `nil` if [Response].Body is already auto-unmarshal performed.
 func (r *Response) BodyBytes() []byte {
 	if r.RawResponse == nil {
 		return []byte{}
@@ -42,18 +42,6 @@ func (r *Response) BodyBytes() []byte {
 	return r.bodyBytes
 }
 
-// SetBodyBytes method sets [Response] body in byte slice. Typically,
-// It is helpful for test cases.
-//
-//	resp.SetBodyBytes([]byte("This is test body content"))
-//	resp.SetBodyBytes(nil)
-//
-// NOTE: Returns an empty byte slice on auto-unmarshal scenarios
-func (r *Response) SetBodyBytes(b []byte) *Response {
-	r.bodyBytes = b
-	return r
-}
-
 // Status method returns the HTTP status string for the executed request.
 //
 //	Example: 200 OK
@@ -149,19 +137,6 @@ func (r *Response) Size() int64 {
 	return r.size
 }
 
-// RawBody method exposes the HTTP raw response body. Use this method in conjunction with
-// [Client.SetDoNotParseResponse] or [Request.SetDoNotParseResponse]
-// option; otherwise, you get an error as `read err: http: read on closed response body.`
-//
-// Do not forget to close the body, otherwise you might get into connection leaks, no connection reuse.
-// You have taken over the control of response parsing from Resty.
-func (r *Response) RawBody() io.ReadCloser {
-	if r.RawResponse == nil {
-		return nil
-	}
-	return r.RawResponse.Body
-}
-
 // IsSuccess method returns true if HTTP status `code >= 200 and <= 299` otherwise false.
 func (r *Response) IsSuccess() bool {
 	return r.StatusCode() > 199 && r.StatusCode() < 300
@@ -180,7 +155,7 @@ func (r *Response) setReceivedAt() {
 }
 
 func (r *Response) fmtBodyString(sl int) string {
-	if r.Request.NotParseResponse {
+	if r.Request.DoNotParseResponse {
 		return "***** DO NOT PARSE RESPONSE - Enabled *****"
 	}
 	if len(r.bodyBytes) > 0 {
@@ -188,7 +163,7 @@ func (r *Response) fmtBodyString(sl int) string {
 			return fmt.Sprintf("***** RESPONSE TOO LARGE (size - %d) *****", len(r.bodyBytes))
 		}
 		ct := r.Header().Get(hdrContentTypeKey)
-		if IsJSONType(ct) {
+		if isJSONContentType(ct) {
 			out := acquireBuffer()
 			defer releaseBuffer(out)
 			err := json.Indent(out, r.bodyBytes, "", "   ")
diff --git a/resty.go b/resty.go
index b92522f..35c329c 100644
--- a/resty.go
+++ b/resty.go
@@ -6,8 +6,6 @@
 package resty
 
 import (
-	"encoding/json"
-	"encoding/xml"
 	"math"
 	"net"
 	"net/http"
@@ -169,14 +167,10 @@ func createClient(hc *http.Client) *Client {
 		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: hdrAuthorizationKey,
 		jsonEscapeHTML:         true,
 		httpClient:             hc,
-		debugBodySizeLimit:     math.MaxInt32,
+		debugBodyLimit:         math.MaxInt32,
 		contentTypeEncoders:    make(map[string]ContentTypeEncoder),
 		contentTypeDecoders:    make(map[string]ContentTypeDecoder),
 	}
diff --git a/retry.go b/retry.go
index e7d3960..ff90959 100644
--- a/retry.go
+++ b/retry.go
@@ -91,9 +91,9 @@ func ResetMultipartReaders(value bool) Option {
 	}
 }
 
-// Backoff retries with increasing timeout duration up until X amount of retries
+// backoff retries with increasing timeout duration up until X amount of retries
 // (Default is 3 attempts, Override with option Retries(n))
-func Backoff(operation func() (*Response, error), options ...Option) error {
+func backoff(operation func() (*Response, error), options ...Option) error {
 	// Defaults
 	opts := Options{
 		maxRetries:      defaultMaxRetries,
diff --git a/stream.go b/stream.go
index 513e93d..12dd0d8 100644
--- a/stream.go
+++ b/stream.go
@@ -29,6 +29,13 @@ func encodeJSONEscapeHTML(w io.Writer, v any, esc bool) error {
 	return enc.Encode(v)
 }
 
+func encodeJSONEscapeHTMLIndent(w io.Writer, v any, esc bool, indent string) error {
+	enc := json.NewEncoder(w)
+	enc.SetEscapeHTML(esc)
+	enc.SetIndent("", indent)
+	return enc.Encode(v)
+}
+
 func decodeJSON(r io.Reader, v any) error {
 	dec := json.NewDecoder(r)
 	for {
diff --git a/transport_other.go b/transport_dial.go
similarity index 100%
rename from transport_other.go
rename to transport_dial.go
diff --git a/transport_js.go b/transport_dial_wasm.go
similarity index 58%
rename from transport_js.go
rename to transport_dial_wasm.go
index 6227aa9..1c06779 100644
--- a/transport_js.go
+++ b/transport_dial_wasm.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build js && wasm
-// +build js,wasm
+//go:build (js && wasm) || wasip1
+// +build js,wasm wasip1
 
 package resty
 
@@ -12,6 +12,6 @@ import (
 	"net"
 )
 
-func transportDialContext(dialer *net.Dialer) func(context.Context, string, string) (net.Conn, error) {
+func transportDialContext(_ *net.Dialer) func(context.Context, string, string) (net.Conn, error) {
 	return nil
 }
diff --git a/util.go b/util.go
index 62a9d65..47e6f68 100644
--- a/util.go
+++ b/util.go
@@ -74,19 +74,19 @@ type RateLimiter interface {
 	Allow() bool
 }
 
-var ErrRateLimitExceeded = errors.New("rate limit exceeded")
+var ErrRateLimitExceeded = errors.New("resty: rate limit exceeded")
 
 //‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
 // Package Helper methods
 //_______________________________________________________________________
 
-// IsStringEmpty method tells whether given string is empty or not
-func IsStringEmpty(str string) bool {
+// isStringEmpty method tells whether given string is empty or not
+func isStringEmpty(str string) bool {
 	return len(strings.TrimSpace(str)) == 0
 }
 
-// DetectContentType method is used to figure out `Request.Body` content type for request header
-func DetectContentType(body any) string {
+// detectContentType method is used to figure out `Request.Body` content type for request header
+func detectContentType(body any) string {
 	contentType := plainTextType
 	kind := inferKind(body)
 	switch kind {
@@ -105,16 +105,6 @@ func DetectContentType(body any) string {
 	return contentType
 }
 
-// IsJSONType method is to check JSON content type or not
-func IsJSONType(ct string) bool {
-	return jsonCheck.MatchString(ct)
-}
-
-// IsXMLType method is to check XML content type or not
-func IsXMLType(ct string) bool {
-	return xmlCheck.MatchString(ct)
-}
-
 func isJSONContentType(ct string) bool {
 	return strings.Contains(ct, jsonKey)
 }
@@ -154,7 +144,7 @@ type ResponseLog struct {
 
 func firstNonEmpty(v ...string) string {
 	for _, s := range v {
-		if !IsStringEmpty(s) {
+		if !isStringEmpty(s) {
 			return s
 		}
 	}
@@ -171,7 +161,7 @@ func createMultipartHeader(param, fileName, contentType string) textproto.MIMEHe
 	hdr := make(textproto.MIMEHeader)
 
 	var contentDispositionValue string
-	if IsStringEmpty(fileName) {
+	if isStringEmpty(fileName) {
 		contentDispositionValue = fmt.Sprintf(`form-data; name="%s"`, param)
 	} else {
 		contentDispositionValue = fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
@@ -179,7 +169,7 @@ func createMultipartHeader(param, fileName, contentType string) textproto.MIMEHe
 	}
 	hdr.Set("Content-Disposition", contentDispositionValue)
 
-	if !IsStringEmpty(contentType) {
+	if !isStringEmpty(contentType) {
 		hdr.Set(hdrContentTypeKey, contentType)
 	}
 	return hdr
@@ -244,10 +234,6 @@ func createDirectory(dir string) (err error) {
 	return
 }
 
-func canJSONMarshal(contentType string, kind reflect.Kind) bool {
-	return IsJSONType(contentType) && (kind == reflect.Struct || kind == reflect.Map || kind == reflect.Slice)
-}
-
 func getPointer(v any) any {
 	vv := reflect.ValueOf(v)
 	if vv.Kind() == reflect.Ptr {
@@ -315,31 +301,23 @@ func closeq(v any) {
 
 func silently(_ ...any) {}
 
-func composeHeaders(c *Client, r *Request, hdrs http.Header) string {
-	str := make([]string, 0, len(hdrs))
-	for _, k := range sortHeaderKeys(hdrs) {
-		str = append(str, "\t"+strings.TrimSpace(fmt.Sprintf("%25s: %s", k, strings.Join(hdrs[k], ", "))))
+func composeHeaders(hdr http.Header) string {
+	str := make([]string, 0, len(hdr))
+	for _, k := range sortHeaderKeys(hdr) {
+		str = append(str, "\t"+strings.TrimSpace(fmt.Sprintf("%25s: %s", k, strings.Join(hdr[k], ", "))))
 	}
 	return strings.Join(str, "\n")
 }
 
-func sortHeaderKeys(hdrs http.Header) []string {
-	keys := make([]string, 0, len(hdrs))
-	for key := range hdrs {
+func sortHeaderKeys(hdr http.Header) []string {
+	keys := make([]string, 0, len(hdr))
+	for key := range hdr {
 		keys = append(keys, key)
 	}
 	sort.Strings(keys)
 	return keys
 }
 
-func copyHeaders(hdrs http.Header) http.Header {
-	nh := http.Header{}
-	for k, v := range hdrs {
-		nh[k] = v
-	}
-	return nh
-}
-
 func wrapErrors(n error, inner error) error {
 	if n == nil && inner == nil {
 		return nil


Test patch:
diff --git a/client_test.go b/client_test.go
index d1dd2e3..90aa876 100644
--- a/client_test.go
+++ b/client_test.go
@@ -12,12 +12,12 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"math"
 	"net"
 	"net/http"
 	"net/url"
 	"os"
 	"path/filepath"
-	"reflect"
 	"strconv"
 	"strings"
 	"sync"
@@ -159,7 +159,7 @@ func TestClientDigestErrors(t *testing.T) {
 }
 
 func TestOnAfterMiddleware(t *testing.T) {
-	ts := createGenServer(t)
+	ts := createGenericServer(t)
 	defer ts.Close()
 
 	c := dc()
@@ -432,115 +432,47 @@ func TestClientSetCookieJar(t *testing.T) {
 	assertEqual(t, true, client.httpClient.Jar == backupJar)
 }
 
-func TestClientOptions(t *testing.T) {
-	client := dc()
-	client.SetContentLength(true)
-	assertEqual(t, client.setContentLength, true)
-
-	client.SetBaseURL("http://httpbin.org")
-	assertEqual(t, "http://httpbin.org", client.BaseURL())
-
-	client.SetHeader(hdrContentTypeKey, "application/json; charset=utf-8")
-	client.SetHeaders(map[string]string{
-		hdrUserAgentKey: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) go-resty v0.1",
-		"X-Request-Id":  strconv.FormatInt(time.Now().UnixNano(), 10),
-	})
-	assertEqual(t, "application/json; charset=utf-8", client.Header().Get(hdrContentTypeKey))
-
-	client.SetCookie(&http.Cookie{
-		Name:  "default-cookie",
-		Value: "This is cookie default-cookie value",
-	})
-	assertEqual(t, "default-cookie", client.Cookies()[0].Name)
-
-	cookies := []*http.Cookie{
-		{
-			Name:  "default-cookie-1",
-			Value: "This is default-cookie 1 value",
-		}, {
-			Name:  "default-cookie-2",
-			Value: "This is default-cookie 2 value",
-		},
-	}
-	client.SetCookies(cookies)
-	assertEqual(t, "default-cookie-1", client.Cookies()[1].Name)
-	assertEqual(t, "default-cookie-2", client.Cookies()[2].Name)
-
-	client.SetQueryParam("test_param_1", "Param_1")
-	client.SetQueryParams(map[string]string{"test_param_2": "Param_2", "test_param_3": "Param_3"})
-	assertEqual(t, "Param_3", client.QueryParams().Get("test_param_3"))
-
-	rTime := strconv.FormatInt(time.Now().UnixNano(), 10)
-	client.SetFormData(map[string]string{"r_time": rTime})
-	assertEqual(t, rTime, client.FormData().Get("r_time"))
-
-	client.SetBasicAuth("myuser", "mypass")
-	assertEqual(t, "myuser", client.UserInfo().Username)
-
-	client.SetAuthToken("AC75BD37F019E08FBC594900518B4F7E")
-	assertEqual(t, "AC75BD37F019E08FBC594900518B4F7E", client.Token())
-
-	client.SetDisableWarn(true)
-	assertEqual(t, client.DisableWarn(), true)
-
-	client.SetRetryCount(3)
-	assertEqual(t, 3, client.RetryCount())
-
-	rwt := time.Duration(1000) * time.Millisecond
-	client.SetRetryWaitTime(rwt)
-	assertEqual(t, rwt, client.RetryWaitTime())
-
-	mrwt := time.Duration(2) * time.Second
-	client.SetRetryMaxWaitTime(mrwt)
-	assertEqual(t, mrwt, client.RetryMaxWaitTime())
-
-	client.AddRetryAfterErrorCondition()
-	equal(client.RetryConditions()[0], func(response *Response, err error) bool {
-		return response.IsError()
-	})
-
-	err := &AuthError{}
-	client.SetError(err)
-	if reflect.TypeOf(err) == client.Error() {
-		t.Error("SetError failed")
-	}
-
-	client.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})
-	transport, transportErr := client.Transport()
-
-	assertNil(t, transportErr)
-	assertEqual(t, true, transport.TLSClientConfig.InsecureSkipVerify)
-
-	client.OnBeforeRequest(func(c *Client, r *Request) error {
-		c.log.Debugf("I'm in Request middleware")
-		return nil // if it success
-	})
-	client.OnAfterResponse(func(c *Client, r *Response) error {
-		c.log.Debugf("I'm in Response middleware")
-		return nil // if it success
-	})
-
-	client.SetTimeout(5 * time.Second)
-	client.SetRedirectPolicy(FlexibleRedirectPolicy(10), func(req *http.Request, via []*http.Request) error {
-		return errors.New("sample test redirect")
-	})
-	client.SetContentLength(true)
+// This test methods exist for test coverage purpose
+// to validate the getter and setter
+func TestClientSettingsCoverage(t *testing.T) {
+	c := dc()
 
-	client.SetDebug(true)
-	assertEqual(t, client.Debug(), true)
+	assertNotNil(t, c.CookieJar())
+	assertNotNil(t, c.ContentTypeEncoders())
+	assertNotNil(t, c.ContentTypeDecoders())
+	assertEqual(t, false, c.IsDebug())
+	assertEqual(t, math.MaxInt32, c.DebugBodyLimit())
+	assertNotNil(t, c.Logger())
+	assertEqual(t, false, c.IsContentLength())
+	assertEqual(t, 0, c.RetryCount())
+	assertEqual(t, time.Millisecond*100, c.RetryWaitTime())
+	assertEqual(t, time.Second*2, c.RetryMaxWaitTime())
+	assertEqual(t, false, c.IsTrace())
+
+	authToken := "sample auth token value"
+	c.SetAuthToken(authToken)
+	assertEqual(t, authToken, c.AuthToken())
+
+	type brokenRedirectPolicy struct{}
+	c.SetRedirectPolicy(&brokenRedirectPolicy{})
+
+	c.SetCloseConnection(true)
+
+	// [Start] Custom Transport scenario
+	ct := dc()
+	ct.SetTransport(&CustomRoundTripper{})
+	_, err := ct.Transport()
+	assertNotNil(t, err)
+	assertEqual(t, ErrNotHttpTransportType, err)
 
-	var sl int = 1000000
-	client.SetDebugBodyLimit(sl)
-	assertEqual(t, client.debugBodySizeLimit, sl)
+	ct.SetProxy("http://localhost:8080")
+	ct.RemoveProxy()
 
-	client.SetAllowGetMethodPayload(true)
-	assertEqual(t, client.AllowGetMethodPayload(), true)
+	ct.SetCertificates(tls.Certificate{})
+	ct.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})
 
-	client.SetScheme("http")
-	assertEqual(t, client.scheme, "http")
-
-	client.SetCloseConnection(true)
-	assertEqual(t, client.closeConnection, true)
+	ct.outputLogTo(io.Discard)
+	// [End] Custom Transport scenario
 }
 
 func TestContentLengthWhenBodyIsNil(t *testing.T) {
@@ -650,13 +582,7 @@ func TestClientRoundTripper(t *testing.T) {
 	ct, err := c.Transport()
 	assertNotNil(t, err)
 	assertNil(t, ct)
-	assertEqual(t, "current transport is not an *http.Transport instance", err.Error())
-
-	c.SetTLSClientConfig(&tls.Config{})
-	c.SetProxy("http://localhost:9090")
-	c.RemoveProxy()
-	c.SetCertificates(tls.Certificate{})
-	c.SetRootCertificate(filepath.Join(getTestDataPath(), "sample-root.pem"))
+	assertEqual(t, ErrNotHttpTransportType, err)
 }
 
 func TestClientNewRequest(t *testing.T) {
@@ -665,38 +591,6 @@ func TestClientNewRequest(t *testing.T) {
 	assertNotNil(t, request)
 }
 
-func TestClientSetJSONMarshaler(t *testing.T) {
-	m := func(v any) ([]byte, error) { return nil, nil }
-	c := New().SetJSONMarshaler(m)
-	p1 := fmt.Sprintf("%p", c.jsonMarshal)
-	p2 := fmt.Sprintf("%p", m)
-	assertEqual(t, p1, p2) // functions can not be compared, we only can compare pointers
-}
-
-func TestClientSetJSONUnmarshaler(t *testing.T) {
-	m := func([]byte, any) error { return nil }
-	c := New().SetJSONUnmarshaler(m)
-	p1 := fmt.Sprintf("%p", c.jsonUnmarshal)
-	p2 := fmt.Sprintf("%p", m)
-	assertEqual(t, p1, p2) // functions can not be compared, we only can compare pointers
-}
-
-func TestClientSetXMLMarshaler(t *testing.T) {
-	m := func(v any) ([]byte, error) { return nil, nil }
-	c := New().SetXMLMarshaler(m)
-	p1 := fmt.Sprintf("%p", c.xmlMarshal)
-	p2 := fmt.Sprintf("%p", m)
-	assertEqual(t, p1, p2) // functions can not be compared, we only can compare pointers
-}
-
-func TestClientSetXMLUnmarshaler(t *testing.T) {
-	m := func([]byte, any) error { return nil }
-	c := New().SetXMLUnmarshaler(m)
-	p1 := fmt.Sprintf("%p", c.xmlUnmarshal)
-	p2 := fmt.Sprintf("%p", m)
-	assertEqual(t, p1, p2) // functions can not be compared, we only can compare pointers
-}
-
 func TestDebugBodySizeLimit(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
@@ -744,7 +638,7 @@ func (rt *CustomRoundTripper) RoundTrip(_ *http.Request) (*http.Response, error)
 }
 
 func TestAutoGzip(t *testing.T) {
-	ts := createGenServer(t)
+	ts := createGenericServer(t)
 	defer ts.Close()
 
 	c := New()
diff --git a/curl_cmd_test.go b/curl_cmd_test.go
index 55cac02..0784fbf 100644
--- a/curl_cmd_test.go
+++ b/curl_cmd_test.go
@@ -20,6 +20,8 @@ func TestGenerateUnexecutedCurl(t *testing.T) {
 			},
 		)
 
+	assertEqual(t, "", req.GenerateCurlCommand())
+
 	curlCmdUnexecuted := req.EnableGenerateCurlOnDebug().GenerateCurlCommand()
 	req.DisableGenerateCurlOnDebug()
 
diff --git a/request_test.go b/request_test.go
index 9bd9130..435943d 100644
--- a/request_test.go
+++ b/request_test.go
@@ -429,7 +429,7 @@ func TestForceContentTypeForGH276andGH240(t *testing.T) {
 	resp, err := c.R().
 		SetBody(map[string]any{"username": "testuser", "password": "testpass"}).
 		SetResult(AuthSuccess{}).
-		ForceContentType("application/json").
+		SetForceResponseContentType("application/json").
 		Post(ts.URL + "/login-json-html")
 
 	assertNil(t, err) // JSON response comes with incorrect content-type, we correct it with ForceContentType
@@ -614,6 +614,27 @@ func TestRequestBasicAuth(t *testing.T) {
 	logResponse(t, resp)
 }
 
+func TestRequestBasicAuthWithBody(t *testing.T) {
+	ts := createAuthServer(t)
+	defer ts.Close()
+
+	c := dc()
+	c.SetBaseURL(ts.URL).
+		SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})
+
+	resp, err := c.R().
+		SetBasicAuth("myuser", "basicauth").
+		SetBody([]string{strings.Repeat("hello", 25)}).
+		SetResult(&AuthSuccess{}).
+		Post("/login")
+
+	assertError(t, err)
+	assertEqual(t, http.StatusOK, resp.StatusCode())
+
+	t.Logf("Result Success: %q", resp.Result().(*AuthSuccess))
+	logResponse(t, resp)
+}
+
 func TestRequestInsecureBasicAuth(t *testing.T) {
 	ts := createAuthServerTLSOptional(t, false)
 	defer ts.Close()
@@ -1101,7 +1122,7 @@ func TestGetWithCookies(t *testing.T) {
 	c.SetBaseURL(ts.URL).SetDebug(true)
 
 	tu, _ := url.Parse(ts.URL)
-	c.GetClient().Jar.SetCookies(tu, []*http.Cookie{
+	c.Client().Jar.SetCookies(tu, []*http.Cookie{
 		{
 			Name:  "jar-go-resty-1",
 			Value: "From Jar - This is cookie 1 value",
@@ -1143,7 +1164,7 @@ func TestGetWithCookies(t *testing.T) {
 }
 
 func TestPutPlainString(t *testing.T) {
-	ts := createGenServer(t)
+	ts := createGenericServer(t)
 	defer ts.Close()
 
 	resp, err := dc().R().
@@ -1156,7 +1177,7 @@ func TestPutPlainString(t *testing.T) {
 }
 
 func TestPutJSONString(t *testing.T) {
-	ts := createGenServer(t)
+	ts := createGenericServer(t)
 	defer ts.Close()
 
 	client := dc()
@@ -1185,7 +1206,7 @@ func TestPutJSONString(t *testing.T) {
 }
 
 func TestPutXMLString(t *testing.T) {
-	ts := createGenServer(t)
+	ts := createGenericServer(t)
 	defer ts.Close()
 
 	resp, err := dc().R().
@@ -1199,7 +1220,7 @@ func TestPutXMLString(t *testing.T) {
 }
 
 func TestOnBeforeMiddleware(t *testing.T) {
-	ts := createGenServer(t)
+	ts := createGenericServer(t)
 	defer ts.Close()
 
 	c := dc()
@@ -1245,42 +1266,55 @@ func TestHostCheckRedirectPolicy(t *testing.T) {
 	assertEqual(t, true, strings.Contains(err.Error(), "redirect is not allowed as per DomainCheckRedirectPolicy"))
 }
 
-func TestHeadMethod(t *testing.T) {
-	ts := createGetServer(t)
+func TestHttpMethods(t *testing.T) {
+	ts := createGenericServer(t)
 	defer ts.Close()
 
-	resp, err := dclr().Head(ts.URL + "/")
+	t.Run("head method", func(t *testing.T) {
+		resp, err := dclr().Head(ts.URL + "/")
 
-	assertError(t, err)
-	assertEqual(t, http.StatusOK, resp.StatusCode())
-}
+		assertError(t, err)
+		assertEqual(t, http.StatusOK, resp.StatusCode())
+	})
 
-func TestOptionsMethod(t *testing.T) {
-	ts := createGenServer(t)
-	defer ts.Close()
+	t.Run("options method", func(t *testing.T) {
+		resp, err := dclr().Options(ts.URL + "/options")
+
+		assertError(t, err)
+		assertEqual(t, http.StatusOK, resp.StatusCode())
+		assertEqual(t, resp.Header().Get("Access-Control-Expose-Headers"), "x-go-resty-id")
+	})
 
-	resp, err := dclr().Options(ts.URL + "/options")
+	t.Run("patch method", func(t *testing.T) {
+		resp, err := dclr().Patch(ts.URL + "/patch")
 
-	assertError(t, err)
-	assertEqual(t, http.StatusOK, resp.StatusCode())
-	assertEqual(t, resp.Header().Get("Access-Control-Expose-Headers"), "x-go-resty-id")
-}
+		assertError(t, err)
+		assertEqual(t, http.StatusOK, resp.StatusCode())
 
-func TestPatchMethod(t *testing.T) {
-	ts := createGenServer(t)
-	defer ts.Close()
+		assertEqual(t, "", resp.String())
+	})
 
-	resp, err := dclr().Patch(ts.URL + "/patch")
+	t.Run("trace method", func(t *testing.T) {
+		resp, err := dclr().Trace(ts.URL + "/trace")
 
-	assertError(t, err)
-	assertEqual(t, http.StatusOK, resp.StatusCode())
+		assertError(t, err)
+		assertEqual(t, http.StatusOK, resp.StatusCode())
 
-	resp.SetBodyBytes(nil)
-	assertEqual(t, "", resp.String())
+		assertEqual(t, "", resp.String())
+	})
+
+	t.Run("connect method", func(t *testing.T) {
+		resp, err := dclr().Connect(ts.URL + "/connect")
+
+		assertError(t, err)
+		assertEqual(t, http.StatusOK, resp.StatusCode())
+
+		assertEqual(t, "", resp.String())
+	})
 }
 
 func TestSendMethod(t *testing.T) {
-	ts := createGenServer(t)
+	ts := createGenericServer(t)
 	defer ts.Close()
 
 	t.Run("send-get", func(t *testing.T) {
@@ -1383,7 +1417,7 @@ func TestProxySetting(t *testing.T) {
 func TestGetClient(t *testing.T) {
 	client := New()
 	custom := New()
-	customClient := custom.GetClient()
+	customClient := custom.Client()
 
 	assertNotNil(t, customClient)
 	assertNotEqual(t, client, http.DefaultClient)
@@ -1602,7 +1636,7 @@ func TestOutputFileWithBaseDirAndRelativePath(t *testing.T) {
 
 	outputFilePath := "go-resty/test-img-success.png"
 	resp, err := client.R().
-		SetOutput(outputFilePath).
+		SetOutputFile(outputFilePath).
 		Get(ts.URL + "/my-image.png")
 
 	assertError(t, err)
@@ -1631,7 +1665,7 @@ func TestOutputPathDirNotExists(t *testing.T) {
 		SetOutputDirectory(filepath.Join(getTestDataPath(), "not-exists-dir"))
 
 	resp, err := client.R().
-		SetOutput("test-img-success.png").
+		SetOutputFile("test-img-success.png").
 		Get(ts.URL + "/my-image.png")
 
 	assertError(t, err)
@@ -1645,7 +1679,7 @@ func TestOutputFileAbsPath(t *testing.T) {
 	defer cleanupFiles(filepath.Join(".testdata", "go-resty"))
 
 	_, err := dcr().
-		SetOutput(filepath.Join(getTestDataPath(), "go-resty", "test-img-success-2.png")).
+		SetOutputFile(filepath.Join(getTestDataPath(), "go-resty", "test-img-success-2.png")).
 		Get(ts.URL + "/my-image.png")
 
 	assertError(t, err)
@@ -1705,10 +1739,10 @@ func TestRequestDoNotParseResponse(t *testing.T) {
 
 	buf := acquireBuffer()
 	defer releaseBuffer(buf)
-	_, _ = io.Copy(buf, resp.RawBody())
+	_, _ = io.Copy(buf, resp.Body)
 
 	assertEqual(t, "TestGet: text response", buf.String())
-	_ = resp.RawBody().Close()
+	_ = resp.Body.Close()
 
 	// Manually setting RawResponse as nil
 	resp, err = dc().R().
@@ -1718,7 +1752,8 @@ func TestRequestDoNotParseResponse(t *testing.T) {
 	assertError(t, err)
 
 	resp.RawResponse = nil
-	assertNil(t, resp.RawBody())
+	assertEqual(t, 0, resp.StatusCode())
+	assertEqual(t, "", resp.String())
 }
 
 func TestRequestDoNotParseResponseDebugLog(t *testing.T) {
@@ -1763,13 +1798,13 @@ type noCtTest struct {
 }
 
 func TestRequestExpectContentTypeTest(t *testing.T) {
-	ts := createGenServer(t)
+	ts := createGenericServer(t)
 	defer ts.Close()
 
 	c := dc()
 	resp, err := c.R().
 		SetResult(noCtTest{}).
-		ExpectContentType("application/json").
+		SetExpectResponseContentType("application/json").
 		Get(ts.URL + "/json-no-set")
 
 	assertError(t, err)
@@ -1802,7 +1837,7 @@ func TestGetPathParamAndPathParams(t *testing.T) {
 }
 
 func TestReportMethodSupportsPayload(t *testing.T) {
-	ts := createGenServer(t)
+	ts := createGenericServer(t)
 	defer ts.Close()
 
 	c := dc()
@@ -2038,7 +2073,7 @@ func TestTraceInfo(t *testing.T) {
 	}
 
 	// for sake of hook funcs
-	_, _ = client.R().EnableTrace().Get("https://httpbin.org/get")
+	_, _ = client.R().SetTrace(true).Get("https://httpbin.org/get")
 }
 
 func TestTraceInfoWithoutEnableTrace(t *testing.T) {
@@ -2088,7 +2123,6 @@ func TestDebugLoggerRequestBodyTooLarge(t *testing.T) {
 	debugBodySizeLimit := 512
 
 	t.Run("upload an image with more than 512 bytes", func(t *testing.T) {
-		// upload an image with more than 512 bytes
 		output := bytes.NewBufferString("")
 		resp, err := New().SetDebug(true).outputLogTo(output).SetDebugBodyLimit(debugBodySizeLimit).R().
 			SetFile("file", filepath.Join(getTestDataPath(), "test-img.png")).
@@ -2100,7 +2134,6 @@ func TestDebugLoggerRequestBodyTooLarge(t *testing.T) {
 	})
 
 	t.Run("upload a text file with no more than 512 bytes", func(t *testing.T) {
-		// upload a text file with no more than 512 bytes
 		output := bytes.NewBufferString("")
 		resp, err := New().outputLogTo(output).SetDebugBodyLimit(debugBodySizeLimit).R().
 			SetDebug(true).
@@ -2116,7 +2149,6 @@ func TestDebugLoggerRequestBodyTooLarge(t *testing.T) {
 	defer formTs.Close()
 
 	t.Run("post form with more than 512 bytes data", func(t *testing.T) {
-		// post form with more than 512 bytes data
 		output := bytes.NewBufferString("")
 		resp, err := New().SetDebug(true).outputLogTo(output).SetDebugBodyLimit(debugBodySizeLimit).R().
 			SetFormData(map[string]string{
@@ -2132,7 +2164,6 @@ func TestDebugLoggerRequestBodyTooLarge(t *testing.T) {
 	})
 
 	t.Run("post form with no more than 512 bytes data", func(t *testing.T) {
-		// post form with no more than 512 bytes data
 		output := bytes.NewBufferString("")
 		resp, err := New().outputLogTo(output).SetDebugBodyLimit(debugBodySizeLimit).R().
 			SetDebug(true).
@@ -2149,7 +2180,6 @@ func TestDebugLoggerRequestBodyTooLarge(t *testing.T) {
 	})
 
 	t.Run("post string with more than 512 bytes data", func(t *testing.T) {
-		// post string with more than 512 bytes data
 		output := bytes.NewBufferString("")
 		resp, err := New().SetDebug(true).outputLogTo(output).SetDebugBodyLimit(debugBodySizeLimit).R().
 			SetBody(`{
@@ -2163,12 +2193,11 @@ func TestDebugLoggerRequestBodyTooLarge(t *testing.T) {
 		assertEqual(t, true, strings.Contains(output.String(), "REQUEST TOO LARGE"))
 	})
 
-	t.Run("post slice with more than 512 bytes data", func(t *testing.T) {
-		// post slice with more than 512 bytes data
+	t.Run("post string slice with more than 512 bytes data", func(t *testing.T) {
 		output := bytes.NewBufferString("")
 		resp, err := New().outputLogTo(output).SetDebugBodyLimit(debugBodySizeLimit).R().
 			SetDebug(true).
-			SetBody([]string{strings.Repeat("C", int(debugBodySizeLimit))}).
+			SetBody([]string{strings.Repeat("hello", debugBodySizeLimit)}).
 			SetBasicAuth("myuser", "mypass").
 			Post(formTs.URL + "/profile")
 		assertNil(t, err)
@@ -2287,3 +2316,17 @@ func TestRequestClone(t *testing.T) {
 	assertEqual(t, "xmpp-server", parent.SRV.Service)
 	assertEqual(t, "xmpp-server-clone", clone.SRV.Service)
 }
+
+// This test methods exist for test coverage purpose
+// to validate the getter and setter
+func TestRequestSettingsCoverage(t *testing.T) {
+	c := dc()
+
+	c.R().SetCloseConnection(true)
+
+	c.R().DisableTrace()
+
+	srv := []*net.SRV{}
+	srv = append(srv, &net.SRV{})
+	c.R().selectAddr(srv, "/", 1)
+}
diff --git a/resty_test.go b/resty_test.go
index bbb568e..3d8f62d 100644
--- a/resty_test.go
+++ b/resty_test.go
@@ -143,7 +143,7 @@ func handleLoginEndpoint(t *testing.T, w http.ResponseWriter, r *http.Request) {
 		user := &User{}
 
 		// JSON
-		if IsJSONType(r.Header.Get(hdrContentTypeKey)) {
+		if isJSONContentType(r.Header.Get(hdrContentTypeKey)) {
 			jd := json.NewDecoder(r.Body)
 			err := jd.Decode(user)
 			if r.URL.Query().Get("ct") == "problem" {
@@ -174,7 +174,7 @@ func handleLoginEndpoint(t *testing.T, w http.ResponseWriter, r *http.Request) {
 		}
 
 		// XML
-		if IsXMLType(r.Header.Get(hdrContentTypeKey)) {
+		if isXMLContentType(r.Header.Get(hdrContentTypeKey)) {
 			xd := xml.NewDecoder(r.Body)
 			err := xd.Decode(user)
 
@@ -208,7 +208,7 @@ func handleLoginEndpoint(t *testing.T, w http.ResponseWriter, r *http.Request) {
 func handleUsersEndpoint(t *testing.T, w http.ResponseWriter, r *http.Request) {
 	if r.URL.Path == "/users" {
 		// JSON
-		if IsJSONType(r.Header.Get(hdrContentTypeKey)) {
+		if isJSONContentType(r.Header.Get(hdrContentTypeKey)) {
 			var users []ExampleUser
 			jd := json.NewDecoder(r.Body)
 			err := jd.Decode(&users)
@@ -258,7 +258,7 @@ func createPostServer(t *testing.T) *httptest.Server {
 				return
 			case "/usersmap":
 				// JSON
-				if IsJSONType(r.Header.Get(hdrContentTypeKey)) {
+				if isJSONContentType(r.Header.Get(hdrContentTypeKey)) {
 					if r.URL.Query().Get("status") == "500" {
 						body, err := io.ReadAll(r.Body)
 						if err != nil {
@@ -529,6 +529,8 @@ func createAuthServerTLSOptional(t *testing.T, useTLS bool) *httptest.Server {
 				auth := r.Header.Get("Authorization")
 				t.Logf("Basic Auth: %v", auth)
 
+				_, _ = io.ReadAll(r.Body)
+
 				w.Header().Set(hdrContentTypeKey, "application/json; charset=utf-8")
 
 				password, err := base64.StdEncoding.DecodeString(auth[6:])
@@ -552,7 +554,7 @@ func createAuthServerTLSOptional(t *testing.T, useTLS bool) *httptest.Server {
 	return httptest.NewServer(handler)
 }
 
-func createGenServer(t *testing.T) *httptest.Server {
+func createGenericServer(t *testing.T) *httptest.Server {
 	ts := createTestServer(func(w http.ResponseWriter, r *http.Request) {
 		t.Logf("Method: %v", r.Method)
 		t.Logf("Path: %v", r.URL.Path)
@@ -618,6 +620,16 @@ func createGenServer(t *testing.T) *httptest.Server {
 			}
 			return
 		}
+
+		if r.Method == MethodTrace && r.URL.Path == "/trace" {
+			w.WriteHeader(http.StatusOK)
+			return
+		}
+
+		if r.Method == MethodConnect && r.URL.Path == "/connect" {
+			w.WriteHeader(http.StatusOK)
+			return
+		}
 	})
 
 	return ts
diff --git a/retry_test.go b/retry_test.go
index 9d80331..7512777 100644
--- a/retry_test.go
+++ b/retry_test.go
@@ -22,7 +22,7 @@ import (
 func TestBackoffSuccess(t *testing.T) {
 	attempts := 3
 	externalCounter := 0
-	retryErr := Backoff(func() (*Response, error) {
+	retryErr := backoff(func() (*Response, error) {
 		externalCounter++
 		if externalCounter < attempts {
 			return nil, errors.New("not yet got the number we're after")
@@ -54,7 +54,7 @@ func TestBackoffNoWaitForLastRetry(t *testing.T) {
 		},
 	}
 
-	retryErr := Backoff(func() (*Response, error) {
+	retryErr := backoff(func() (*Response, error) {
 		externalCounter++
 		return resp, nil
 	}, RetryConditions([]RetryConditionFunc{func(response *Response, err error) bool {
@@ -71,7 +71,7 @@ func TestBackoffNoWaitForLastRetry(t *testing.T) {
 func TestBackoffTenAttemptsSuccess(t *testing.T) {
 	attempts := 10
 	externalCounter := 0
-	retryErr := Backoff(func() (*Response, error) {
+	retryErr := backoff(func() (*Response, error) {
 		externalCounter++
 		if externalCounter < attempts {
 			return nil, errors.New("not yet got the number we're after")
@@ -90,7 +90,7 @@ func TestConditionalBackoffCondition(t *testing.T) {
 	check := RetryConditionFunc(func(*Response, error) bool {
 		return attempts != counter
 	})
-	retryErr := Backoff(func() (*Response, error) {
+	retryErr := backoff(func() (*Response, error) {
 		counter++
 		return nil, nil
 	}, RetryConditions([]RetryConditionFunc{check}))
@@ -104,7 +104,7 @@ func TestConditionalBackoffConditionNonExecution(t *testing.T) {
 	attempts := 3
 	counter := 0
 
-	retryErr := Backoff(func() (*Response, error) {
+	retryErr := backoff(func() (*Response, error) {
 		counter++
 		return nil, nil
 	}, RetryConditions([]RetryConditionFunc{filler}))
@@ -122,7 +122,7 @@ func TestOnRetryBackoff(t *testing.T) {
 		counter++
 	}
 
-	retryErr := Backoff(func() (*Response, error) {
+	retryErr := backoff(func() (*Response, error) {
 		return nil, nil
 	}, RetryHooks([]OnRetryFunc{hook}))
 
diff --git a/util_test.go b/util_test.go
index 7bc5db1..ccf816c 100644
--- a/util_test.go
+++ b/util_test.go
@@ -12,7 +12,7 @@ import (
 	"testing"
 )
 
-func TestIsJSONType(t *testing.T) {
+func TestIsJSONContentType(t *testing.T) {
 	for _, test := range []struct {
 		input  string
 		expect bool
@@ -38,7 +38,7 @@ func TestIsJSONType(t *testing.T) {
 		{"text/vnd.foo-json", true},
 		{"text/vnd.foo.json", true},
 	} {
-		result := IsJSONType(test.input)
+		result := isJSONContentType(test.input)
 
 		if result != test.expect {
 			t.Errorf("failed on %q: want %v, got %v", test.input, test.expect, result)
@@ -46,7 +46,7 @@ func TestIsJSONType(t *testing.T) {
 	}
 }
 
-func TestIsXMLType(t *testing.T) {
+func TestIsXMLContentType(t *testing.T) {
 	for _, test := range []struct {
 		input  string
 		expect bool
@@ -70,7 +70,7 @@ func TestIsXMLType(t *testing.T) {
 		{"text/vnd.foo-xml", true},
 		{"text/vnd.foo.xml", true},
 	} {
-		result := IsXMLType(test.input)
+		result := isXMLContentType(test.input)
 
 		if result != test.expect {
 			t.Errorf("failed on %q: want %v, got %v", test.input, test.expect, result)