Repository: go-resty/resty
Pull request #869 (2024-09-25 04:43:52)

Debug logger, unlimited response body reads and helper methods

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/go-resty/resty/pull/869?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty) Report
Attention: Patch coverage is `96.93878%` with `6 lines` in your changes missing coverage. Please review.
> Project coverage is 97.99%. Comparing base [(`bc3024b`)](https://app.codecov.io/gh/go-resty/resty/commit/bc3024b43c09db6d1cbb682d49dea4d1d4cb7234?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty) to head [(`cfc8b56`)](https://app.codecov.io/gh/go-resty/resty/commit/cfc8b5659081112a85c7922b203a8137ef5adb67?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty).
> Report is 1 commits behind head on main.

| [Files with missing lines](https://app.codecov.io/gh/go-resty/resty/pull/869?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty) | Patch % | Lines |
|---|---|---|
| [util\_curl.go](https://app.codecov.io/gh/go-resty/resty/pull/869?src=pr&el=tree&filepath=util_curl.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty#diff-dXRpbF9jdXJsLmdv) | 70.00% | [1 Missing and 2 partials :warning: ](https://app.codecov.io/gh/go-resty/resty/pull/869?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty) |
| [client.go](https://app.codecov.io/gh/go-resty/resty/pull/869?src=pr&el=tree&filepath=client.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty#diff-Y2xpZW50Lmdv) | 96.22% | [1 Missing and 1 partial :warning: ](https://app.codecov.io/gh/go-resty/resty/pull/869?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty) |
| [response.go](https://app.codecov.io/gh/go-resty/resty/pull/869?src=pr&el=tree&filepath=response.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty#diff-cmVzcG9uc2UuZ28=) | 97.14% | [1 Missing :warning: ](https://app.codecov.io/gh/go-resty/resty/pull/869?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main     #869      +/-   ##
==========================================
+ Coverage   97.62%   97.99%   +0.37%     
==========================================
  Files          14       14              
  Lines        2185     2241      +56     
==========================================
+ Hits         2133     2196      +63     
+ Misses         32       25       -7     
  Partials       20       20              
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/go-resty/resty/pull/869?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty).


Patch:
diff --git a/client.go b/client.go
index fcd0e1d..51b98ee 100644
--- a/client.go
+++ b/client.go
@@ -177,6 +177,7 @@ type Client struct {
 	retryResetReaders      bool
 	headerAuthorizationKey string
 	responseBodyLimit      int64
+	resBodyUnlimitedReads  bool
 	jsonEscapeHTML         bool
 	setContentLength       bool
 	closeConnection        bool
@@ -563,24 +564,26 @@ 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,
-		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,
+		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,
+		IsTrace:                    c.isTrace,
+		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,
+		ResponseBodyUnlimitedReads: c.resBodyUnlimitedReads,
 
 		client:              c,
 		multipartFiles:      []*File{},
@@ -588,7 +591,6 @@ func (c *Client) R() *Request {
 		jsonEscapeHTML:      c.jsonEscapeHTML,
 		log:                 c.log,
 		setContentLength:    c.setContentLength,
-		IsTrace:             c.isTrace,
 		generateCurlOnDebug: c.generateCurlOnDebug,
 	}
 
@@ -781,6 +783,18 @@ func (c *Client) IsDebug() bool {
 	return c.debug
 }
 
+// EnableDebug method is a helper method for [Client.SetDebug]
+func (c *Client) EnableDebug() *Client {
+	c.SetDebug(true)
+	return c
+}
+
+// DisableDebug method is a helper method for [Client.SetDebug]
+func (c *Client) DisableDebug() *Client {
+	c.SetDebug(false)
+	return c
+}
+
 // SetDebug method enables the debug mode on the Resty client. The client logs details
 // of every request and response.
 //
@@ -1609,6 +1623,30 @@ func (c *Client) SetGenerateCurlOnDebug(b bool) *Client {
 	return c
 }
 
+// ResponseBodyUnlimitedReads method returns true if enabled. Otherwise, it returns false
+func (c *Client) ResponseBodyUnlimitedReads() bool {
+	c.lock.RLock()
+	defer c.lock.RUnlock()
+	return c.resBodyUnlimitedReads
+}
+
+// SetResponseBodyUnlimitedReads method is to turn on/off the response body copy
+// that provides an ability to do unlimited reads.
+//
+// It can be overridden at the request level; see [Request.SetResponseBodyUnlimitedReads]
+//
+// NOTE: Turning on this feature uses additional memory to store a copy of the response body buffer.
+//
+// Unlimited reads are possible in a few scenarios, even without enabling this method.
+//   - When [Client.SetDebug] set to true
+//   - When [Request.SetResult] or [Request.SetError] methods are not used
+func (c *Client) SetResponseBodyUnlimitedReads(b bool) *Client {
+	c.lock.Lock()
+	defer c.lock.Unlock()
+	c.resBodyUnlimitedReads = b
+	return c
+}
+
 // IsProxySet method returns the true is proxy is set from the Resty client; otherwise
 // false. By default, the proxy is set from the environment variable; refer to [http.ProxyFromEnvironment].
 func (c *Client) IsProxySet() bool {
@@ -1639,9 +1677,12 @@ func (c *Client) Clone() *Client {
 }
 
 func (c *Client) executeBefore(req *Request) error {
-	// Apply Request middleware
 	var err error
 
+	if isStringEmpty(req.Method) {
+		req.Method = MethodGet
+	}
+
 	// user defined on before request methods
 	// to modify the *resty.Request object
 	for _, f := range c.beforeRequestMiddlewares() {
@@ -1676,11 +1717,6 @@ func (c *Client) executeBefore(req *Request) error {
 		}
 	}
 
-	if err = requestLogger(c, req); err != nil {
-		return wrapNoRetryErr(err)
-	}
-
-	req.RawRequest.Body = newRequestBodyReleaser(req.RawRequest.Body, req.bodyBuf)
 	return nil
 }
 
@@ -1691,27 +1727,39 @@ func (c *Client) execute(req *Request) (*Response, error) {
 		return nil, err
 	}
 
+	if err := requestDebugLogger(c, req); err != nil {
+		return nil, wrapNoRetryErr(err)
+	}
+
+	req.RawRequest.Body = wrapRequestBufferReleaser(req)
 	req.Time = time.Now()
 	resp, err := c.Client().Do(req.RawRequest)
 
-	response := &Response{
-		Request:     req,
-		RawResponse: resp,
-	}
-
+	response := &Response{Request: req, RawResponse: resp}
 	response.setReceivedAt()
+	if err != nil {
+		return response, err
+	}
 	if resp != nil {
-		response.Body = &limitReadCloser{
-			r: resp.Body,
+		response.Body = &limitReadCloser{r: resp.Body,
 			l: req.ResponseBodyLimit,
-			f: func(s int64) {
-				response.size = s
-			},
+			f: func(s int64) { response.size = s },
+		}
+	}
+	if !req.DoNotParseResponse && (req.Debug || req.ResponseBodyUnlimitedReads) {
+		response.wrapReadCopier()
+
+		if err := response.readAllBytes(); err != nil {
+			return response, err
 		}
 	}
 
-	if err != nil || req.DoNotParseResponse { // error or do not parse response
-		return response, wrapErrors(responseLogger(c, response), err)
+	if err := responseDebugLogger(c, response); err != nil {
+		return response, err
+	}
+
+	if req.DoNotParseResponse {
+		return response, err
 	}
 
 	// Apply Response middleware
@@ -1720,11 +1768,6 @@ func (c *Client) execute(req *Request) (*Response, error) {
 			return response, err
 		}
 	}
-	// TODO figure out debug response logger with body copy, etc.
-	err = responseLogger(c, response)
-	if err != nil {
-		return response, wrapNoRetryErr(err)
-	}
 
 	return response, wrapNoRetryErr(err)
 }
diff --git a/middleware.go b/middleware.go
index 2f16bae..4da98da 100644
--- a/middleware.go
+++ b/middleware.go
@@ -212,6 +212,7 @@ func createHTTPRequest(c *Client, r *Request) (err error) {
 		}
 	} else {
 		// fix data race: must deep copy.
+		// TODO investigate in details and remove this copy line
 		bodyBuf := bytes.NewBuffer(append([]byte{}, r.bodyBuf.Bytes()...))
 		r.RawRequest, err = http.NewRequest(r.Method, r.URL, bodyBuf)
 	}
@@ -247,19 +248,6 @@ func createHTTPRequest(c *Client, r *Request) (err error) {
 		r.RawRequest = r.RawRequest.WithContext(r.ctx)
 	}
 
-	bodyCopy, err := getBodyCopy(r)
-	if err != nil {
-		return err
-	}
-
-	// assign get body func for the underlying raw request instance
-	r.RawRequest.GetBody = func() (io.ReadCloser, error) {
-		if bodyCopy != nil {
-			return io.NopCloser(bytes.NewReader(bodyCopy.Bytes())), nil
-		}
-		return nil, nil
-	}
-
 	return
 }
 
@@ -296,49 +284,51 @@ func createCurlCmd(c *Client, r *Request) (err error) {
 		if r.resultCurlCmd == nil {
 			r.resultCurlCmd = new(string)
 		}
-		*r.resultCurlCmd = buildCurlRequest(r.RawRequest, c.Client().Jar)
+		*r.resultCurlCmd = buildCurlRequest(r)
 	}
 	return nil
 }
 
-func requestLogger(c *Client, r *Request) error {
-	if r.Debug {
-		rr := r.RawRequest
-		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)
-				} else {
-					rh.Set("Cookie", s)
-				}
+func requestDebugLogger(c *Client, r *Request) error {
+	if !r.Debug {
+		return nil
+	}
+
+	rr := r.RawRequest
+	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)
+			} else {
+				rh.Set("Cookie", s)
 			}
 		}
-		rl := &RequestLog{Header: rh, Body: r.fmtBodyString(r.DebugBodyLimit)}
-		if c.requestLog != nil {
-			if err := c.requestLog(rl); err != nil {
-				return err
-			}
+	}
+	rl := &RequestLog{Header: rh, Body: r.fmtBodyString(r.DebugBodyLimit)}
+	if c.requestLog != nil {
+		if err := c.requestLog(rl); err != nil {
+			return err
 		}
+	}
 
-		reqLog := "\n==============================================================================\n"
+	reqLog := "\n==============================================================================\n"
 
-		if r.Debug && r.generateCurlOnDebug {
-			reqLog += "~~~ REQUEST(CURL) ~~~\n" +
-				fmt.Sprintf("	%v\n", *r.resultCurlCmd)
-		}
+	if r.Debug && r.generateCurlOnDebug {
+		reqLog += "~~~ REQUEST(CURL) ~~~\n" +
+			fmt.Sprintf("	%v\n", *r.resultCurlCmd)
+	}
 
-		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(rl.Header)) +
-			fmt.Sprintf("BODY   :\n%v\n", rl.Body) +
-			"------------------------------------------------------------------------------\n"
+	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(rl.Header)) +
+		fmt.Sprintf("BODY   :\n%v\n", rl.Body) +
+		"------------------------------------------------------------------------------\n"
 
-		r.initValuesMap()
-		r.values[debugRequestLogKey] = reqLog
-	}
+	r.initValuesMap()
+	r.values[debugRequestLogKey] = reqLog
 
 	return nil
 }
@@ -347,40 +337,47 @@ func requestLogger(c *Client, r *Request) error {
 // Response Middleware(s)
 //_______________________________________________________________________
 
-func responseLogger(c *Client, res *Response) error {
-	if res.Request.Debug {
-		rl := &ResponseLog{Header: res.Header().Clone(), Body: res.fmtBodyString(res.Request.DebugBodyLimit)}
-		if c.responseLog != nil {
-			c.lock.RLock()
-			defer c.lock.RUnlock()
-			if err := c.responseLog(rl); err != nil {
-				return err
-			}
-		}
+func responseDebugLogger(c *Client, res *Response) error {
+	if !res.Request.Debug {
+		return nil
+	}
 
-		debugLog := res.Request.values[debugRequestLogKey].(string)
-		debugLog += "~~~ RESPONSE ~~~\n" +
-			fmt.Sprintf("STATUS       : %s\n", res.Status()) +
-			fmt.Sprintf("PROTO        : %s\n", res.RawResponse.Proto) +
-			fmt.Sprintf("RECEIVED AT  : %v\n", res.ReceivedAt().Format(time.RFC3339Nano)) +
-			fmt.Sprintf("TIME DURATION: %v\n", res.Time()) +
-			"HEADERS      :\n" +
-			composeHeaders(rl.Header) + "\n"
-		if res.Request.isSaveResponse {
-			debugLog += "BODY         :\n***** RESPONSE WRITTEN INTO FILE *****\n"
-		} else {
-			debugLog += fmt.Sprintf("BODY         :\n%v\n", rl.Body)
+	bodyStr, err := res.fmtBodyString(res.Request.DebugBodyLimit)
+	if err != nil {
+		return err
+	}
+
+	rl := &ResponseLog{Header: res.Header().Clone(), Body: bodyStr}
+	if c.responseLog != nil {
+		c.lock.RLock()
+		defer c.lock.RUnlock()
+		if err := c.responseLog(rl); err != nil {
+			return err
 		}
-		debugLog += "==============================================================================\n"
+	}
 
-		res.Request.log.Debugf("%s", debugLog)
+	debugLog := res.Request.values[debugRequestLogKey].(string)
+	debugLog += "~~~ RESPONSE ~~~\n" +
+		fmt.Sprintf("STATUS       : %s\n", res.Status()) +
+		fmt.Sprintf("PROTO        : %s\n", res.RawResponse.Proto) +
+		fmt.Sprintf("RECEIVED AT  : %v\n", res.ReceivedAt().Format(time.RFC3339Nano)) +
+		fmt.Sprintf("TIME DURATION: %v\n", res.Time()) +
+		"HEADERS      :\n" +
+		composeHeaders(rl.Header) + "\n"
+	if res.Request.isSaveResponse {
+		debugLog += "BODY         :\n***** RESPONSE WRITTEN INTO FILE *****\n"
+	} else {
+		debugLog += fmt.Sprintf("BODY         :\n%v\n", rl.Body)
 	}
+	debugLog += "==============================================================================\n"
+
+	res.Request.log.Debugf("%s", debugLog)
 
 	return nil
 }
 
 func parseResponseBody(c *Client, res *Response) (err error) {
-	if res.Request.isSaveResponse {
+	if res.Request.DoNotParseResponse || res.Request.isSaveResponse {
 		return // move on
 	}
 
@@ -409,6 +406,7 @@ func parseResponseBody(c *Client, res *Response) (err error) {
 		res.Request.Error = nil
 		defer closeq(res.Body)
 		err = decFunc(res.Body, res.Request.Result)
+		res.IsRead = true
 		return
 	}
 
@@ -422,6 +420,7 @@ func parseResponseBody(c *Client, res *Response) (err error) {
 		if res.Request.Error != nil {
 			defer closeq(res.Body)
 			err = decFunc(res.Body, res.Request.Error)
+			res.IsRead = true
 			return
 		}
 	}
@@ -587,32 +586,3 @@ func saveResponseIntoFile(c *Client, res *Response) error {
 
 	return nil
 }
-
-func getBodyCopy(r *Request) (*bytes.Buffer, error) {
-	// If r.bodyBuf present, return the copy
-	if r.bodyBuf != nil {
-		bodyCopy := acquireBuffer()
-		if _, err := io.Copy(bodyCopy, bytes.NewReader(r.bodyBuf.Bytes())); err != nil {
-			// cannot use io.Copy(bodyCopy, r.bodyBuf) because io.Copy reset r.bodyBuf
-			return nil, err
-		}
-		return bodyCopy, nil
-	}
-
-	// Maybe body is `io.Reader`.
-	// Note: Resty user have to watchout for large body size of `io.Reader`
-	if r.RawRequest.Body != nil {
-		b, err := io.ReadAll(r.RawRequest.Body)
-		if err != nil {
-			return nil, err
-		}
-
-		// Restore the Body
-		closeq(r.RawRequest.Body)
-		r.RawRequest.Body = io.NopCloser(bytes.NewBuffer(b))
-
-		// Return the Body bytes
-		return bytes.NewBuffer(b), nil
-	}
-	return nil, nil
-}
diff --git a/request.go b/request.go
index 491dc97..bda317f 100644
--- a/request.go
+++ b/request.go
@@ -27,32 +27,33 @@ 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
-	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
+	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
+	ResponseBodyUnlimitedReads bool
+	IsTrace                    bool
 
 	// Retry
 	RetryCount        int
@@ -99,10 +100,16 @@ func (r *Request) GenerateCurlCommand() string {
 	if r.resultCurlCmd == nil {
 		r.resultCurlCmd = new(string)
 	}
-	*r.resultCurlCmd = buildCurlRequest(r.RawRequest, r.client.httpClient.Jar)
+	*r.resultCurlCmd = buildCurlRequest(r)
 	return *r.resultCurlCmd
 }
 
+// SetMethod method used to set the HTTP verb for the request
+func (r *Request) SetMethod(m string) *Request {
+	r.Method = m
+	return r
+}
+
 // Context method returns the Context if it is already set in the [Request]
 // otherwise, it creates a new one using [context.Background].
 func (r *Request) Context() context.Context {
@@ -660,6 +667,21 @@ func (r *Request) SetResponseBodyLimit(v int64) *Request {
 	return r
 }
 
+// SetResponseBodyUnlimitedReads method is to turn on/off the response body copy
+// that provides an ability to do unlimited reads.
+//
+// It overriddes the value set at client level; see [Client.SetResponseBodyUnlimitedReads]
+//
+// NOTE: Turning on this feature uses additional memory to store a copy of the response body buffer.
+//
+// Unlimited reads are possible in a few scenarios, even without enabling this method.
+//   - When [Client.SetDebug] or [Request.SetDebug] set to true
+//   - When [Request.SetResult] or [Request.SetError] methods are not used
+func (r *Request) SetResponseBodyUnlimitedReads(b bool) *Request {
+	r.ResponseBodyUnlimitedReads = b
+	return r
+}
+
 // SetPathParam method sets a single URL path key-value pair in the
 // Resty current request instance.
 //
@@ -831,6 +853,18 @@ func (r *Request) SetLogger(l Logger) *Request {
 	return r
 }
 
+// EnableDebug method is a helper method for [Request.SetDebug]
+func (r *Request) EnableDebug() *Request {
+	r.SetDebug(true)
+	return r
+}
+
+// DisableDebug method is a helper method for [Request.SetDebug]
+func (r *Request) DisableDebug() *Request {
+	r.SetDebug(false)
+	return r
+}
+
 // SetDebug method enables the debug mode on the current request. It logs
 // the details current request and response.
 //
@@ -1250,7 +1284,7 @@ func (r *Request) fmtBodyString(sl int) (body string) {
 		(kind == reflect.Struct || kind == reflect.Map || kind == reflect.Slice) {
 		buf := acquireBuffer()
 		defer releaseBuffer(buf)
-		if err = encodeJSONEscapeHTMLIndent(buf, r.Body, false, "   "); err == nil {
+		if err = encodeJSONEscapeHTMLIndent(buf, &r.Body, false, "   "); err == nil {
 			prtBodyBytes = buf.Bytes()
 		}
 	} else if xmlKey == ctKey && kind == reflect.Struct {
diff --git a/response.go b/response.go
index ca11b1a..4afa625 100644
--- a/response.go
+++ b/response.go
@@ -23,6 +23,7 @@ type Response struct {
 	Request     *Request
 	Body        io.ReadCloser
 	RawResponse *http.Response
+	IsRead      bool
 
 	bodyBytes  []byte
 	size       int64
@@ -35,6 +36,8 @@ type Response struct {
 //   - [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 auto-unmarshal performed.
+//
+// TODO remove it
 func (r *Response) BodyBytes() []byte {
 	if r.RawResponse == nil {
 		return []byte{}
@@ -106,8 +109,8 @@ func (r *Response) Cookies() []*http.Cookie {
 // NOTE:
 //   - Returns an empty string on auto-unmarshal scenarios
 func (r *Response) String() string {
-	if len(r.bodyBytes) == 0 {
-		return ""
+	if len(r.bodyBytes) == 0 && !r.Request.DoNotParseResponse {
+		_ = r.readAllBytes()
 	}
 	return strings.TrimSpace(string(r.bodyBytes))
 }
@@ -154,35 +157,66 @@ func (r *Response) setReceivedAt() {
 	}
 }
 
-func (r *Response) fmtBodyString(sl int) string {
+func (r *Response) fmtBodyString(sl int) (string, error) {
 	if r.Request.DoNotParseResponse {
-		return "***** DO NOT PARSE RESPONSE - Enabled *****"
+		return "***** DO NOT PARSE RESPONSE - Enabled *****", nil
+	}
+
+	bl := len(r.bodyBytes)
+	if r.IsRead && bl == 0 {
+		return "***** RESPONSE BODY IS ALREADY READ - see Response.{Result()/Error()} *****", nil
 	}
-	if len(r.bodyBytes) > 0 {
-		if len(r.bodyBytes) > sl {
-			return fmt.Sprintf("***** RESPONSE TOO LARGE (size - %d) *****", len(r.bodyBytes))
+
+	if bl > 0 {
+		if bl > sl {
+			return fmt.Sprintf("***** RESPONSE TOO LARGE (size - %d) *****", bl), nil
 		}
+
 		ct := r.Header().Get(hdrContentTypeKey)
-		if isJSONContentType(ct) {
+		ctKey := inferContentTypeMapKey(ct)
+		if jsonKey == ctKey {
 			out := acquireBuffer()
 			defer releaseBuffer(out)
 			err := json.Indent(out, r.bodyBytes, "", "   ")
 			if err != nil {
-				return fmt.Sprintf("*** Error: Unable to format response body - \"%s\" ***\n\nLog Body as-is:\n%s", err, r.String())
+				return "", err
 			}
-			return out.String()
+			return out.String(), nil
 		}
-		return r.String()
+		return r.String(), nil
 	}
 
-	return "***** NO CONTENT *****"
+	return "***** NO CONTENT *****", nil
 }
 
 // auto-unmarshal didn't happen, so fallback to
 // old behavior of reading response as body bytes
 func (r *Response) readAllBytes() (err error) {
-	defer closeq(r.Body)
-	r.bodyBytes, err = io.ReadAll(r.Body)
-	r.Body = io.NopCloser(bytes.NewReader(r.bodyBytes))
+	if r.IsRead {
+		return nil
+	}
+
+	if _, ok := r.Body.(*readCopier); ok {
+		_, err = io.ReadAll(r.Body)
+	} else {
+		r.bodyBytes, err = io.ReadAll(r.Body)
+		closeq(r.Body)
+		r.Body = &readNoOpCloser{r: bytes.NewReader(r.bodyBytes)}
+	}
+
+	r.IsRead = true
 	return
 }
+
+func (r *Response) wrapReadCopier() {
+	r.Body = &readCopier{
+		s: r.Body,
+		t: acquireBuffer(),
+		f: func(b *bytes.Buffer) {
+			r.bodyBytes = append([]byte{}, b.Bytes()...)
+			closeq(r.Body)
+			r.Body = &readNoOpCloser{r: bytes.NewReader(r.bodyBytes)}
+			releaseBuffer(b)
+		},
+	}
+}
diff --git a/stream.go b/stream.go
index 12dd0d8..e47f0fb 100644
--- a/stream.go
+++ b/stream.go
@@ -5,6 +5,7 @@
 package resty
 
 import (
+	"bytes"
 	"encoding/json"
 	"encoding/xml"
 	"errors"
@@ -97,3 +98,49 @@ func (l *limitReadCloser) Close() error {
 	}
 	return nil
 }
+
+var _ io.ReadCloser = (*readCopier)(nil)
+
+type readCopier struct {
+	s io.Reader
+	t *bytes.Buffer
+	c bool
+	f func(*bytes.Buffer)
+}
+
+func (r *readCopier) Read(p []byte) (int, error) {
+	n, err := r.s.Read(p)
+	if n > 0 {
+		_, _ = r.t.Write(p[:n])
+	}
+	if err == io.EOF || err == ErrReadExceedsThresholdLimit {
+		if !r.c {
+			r.f(r.t)
+			r.c = true
+		}
+	}
+	return n, err
+}
+
+func (r *readCopier) Close() error {
+	if c, ok := r.s.(io.Closer); ok {
+		return c.Close()
+	}
+	return nil
+}
+
+var _ io.ReadCloser = (*readNoOpCloser)(nil)
+
+type readNoOpCloser struct {
+	r *bytes.Reader
+}
+
+func (r *readNoOpCloser) Read(p []byte) (int, error) {
+	n, err := r.r.Read(p)
+	if err == io.EOF {
+		r.r.Seek(0, 0)
+	}
+	return n, err
+}
+
+func (r *readNoOpCloser) Close() error { return nil }
diff --git a/util.go b/util.go
index 47e6f68..cd65faa 100644
--- a/util.go
+++ b/util.go
@@ -265,26 +265,27 @@ func releaseBuffer(buf *bytes.Buffer) {
 	}
 }
 
-// requestBodyReleaser wraps requests's body and implements custom Close for it.
+func wrapRequestBufferReleaser(r *Request) io.ReadCloser {
+	if r.bodyBuf == nil {
+		return r.RawRequest.Body
+	}
+	return &requestBufferReleaser{
+		reqBuf:     r.bodyBuf,
+		ReadCloser: r.RawRequest.Body,
+	}
+}
+
+var _ io.ReadCloser = (*requestBufferReleaser)(nil)
+
+// requestBufferReleaser wraps request body and implements custom Close for it.
 // The Close method closes original body and releases request body back to sync.Pool.
-type requestBodyReleaser struct {
+type requestBufferReleaser struct {
 	releaseOnce sync.Once
 	reqBuf      *bytes.Buffer
 	io.ReadCloser
 }
 
-func newRequestBodyReleaser(respBody io.ReadCloser, reqBuf *bytes.Buffer) io.ReadCloser {
-	if reqBuf == nil {
-		return respBody
-	}
-
-	return &requestBodyReleaser{
-		reqBuf:     reqBuf,
-		ReadCloser: respBody,
-	}
-}
-
-func (rr *requestBodyReleaser) Close() error {
+func (rr *requestBufferReleaser) Close() error {
 	err := rr.ReadCloser.Close()
 	rr.releaseOnce.Do(func() {
 		releaseBuffer(rr.reqBuf)
diff --git a/util_curl.go b/util_curl.go
index f899216..92b51d0 100644
--- a/util_curl.go
+++ b/util_curl.go
@@ -4,7 +4,6 @@ import (
 	"bytes"
 	"io"
 	"net/http"
-	"net/http/cookiejar"
 
 	"net/url"
 	"strings"
@@ -12,33 +11,34 @@ import (
 	"github.com/go-resty/resty/v3/shellescape"
 )
 
-func buildCurlRequest(req *http.Request, httpCookiejar http.CookieJar) (curl string) {
+func buildCurlRequest(req *Request) (curl string) {
 	// 1. Generate curl raw headers
-
 	curl = "curl -X " + req.Method + " "
 	// req.Host + req.URL.Path + "?" + req.URL.RawQuery + " " + req.Proto + " "
-	headers := dumpCurlHeaders(req)
+	headers := dumpCurlHeaders(req.RawRequest)
 	for _, kv := range *headers {
 		curl += `-H ` + shellescape.Quote(kv[0]+": "+kv[1]) + ` `
 	}
 
 	// 2. Generate curl cookies
 	// TODO validate this block of code, I think its not required since cookie captured via Headers
-	if cookieJar, ok := httpCookiejar.(*cookiejar.Jar); ok {
-		cookies := cookieJar.Cookies(req.URL)
-		if len(cookies) > 0 {
+	if cookieJar := req.client.CookieJar(); cookieJar != nil {
+		if cookies := cookieJar.Cookies(req.RawRequest.URL); len(cookies) > 0 {
 			curl += ` -H ` + shellescape.Quote(dumpCurlCookies(cookies)) + " "
 		}
 	}
 
 	// 3. Generate curl body
-	if req.Body != nil {
-		buf, _ := io.ReadAll(req.Body)
-		req.Body = io.NopCloser(bytes.NewBuffer(buf)) // important!!
+	if req.RawRequest.GetBody != nil {
+		body, err := req.RawRequest.GetBody()
+		if err != nil {
+			return ""
+		}
+		buf, _ := io.ReadAll(body)
 		curl += `-d ` + shellescape.Quote(string(bytes.TrimRight(buf, "\n")))
 	}
 
-	urlString := shellescape.Quote(req.URL.String())
+	urlString := shellescape.Quote(req.RawRequest.URL.String())
 	if urlString == "''" {
 		urlString = "'http://unexecuted-request'"
 	}


Test patch:
diff --git a/client_test.go b/client_test.go
index 90aa876..b5b4b21 100644
--- a/client_test.go
+++ b/client_test.go
@@ -29,7 +29,7 @@ func TestClientBasicAuth(t *testing.T) {
 	ts := createAuthServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetBasicAuth("myuser", "basicauth").
 		SetBaseURL(ts.URL).
 		SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})
@@ -49,7 +49,7 @@ func TestClientAuthToken(t *testing.T) {
 	ts := createAuthServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}).
 		SetAuthToken("004DDB79-6801-4587-B976-F093E6AC44FF").
 		SetBaseURL(ts.URL + "/")
@@ -64,7 +64,7 @@ func TestClientAuthScheme(t *testing.T) {
 	ts := createAuthServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	// Ensure default Bearer
 	c.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}).
 		SetAuthToken("004DDB79-6801-4587-B976-F093E6AC44FF").
@@ -90,7 +90,7 @@ func TestClientDigestAuth(t *testing.T) {
 	ts := createDigestServer(t, conf)
 	defer ts.Close()
 
-	c := dc().
+	c := dcnl().
 		SetBaseURL(ts.URL+"/").
 		SetDigestAuth(conf.username, conf.password)
 
@@ -111,7 +111,7 @@ func TestClientDigestSession(t *testing.T) {
 	ts := createDigestServer(t, conf)
 	defer ts.Close()
 
-	c := dc().
+	c := dcnl().
 		SetBaseURL(ts.URL+"/").
 		SetDigestAuth(conf.username, conf.password)
 
@@ -148,7 +148,7 @@ func TestClientDigestErrors(t *testing.T) {
 		tc.mutateConf(conf)
 		ts := createDigestServer(t, conf)
 
-		c := dc().
+		c := dcnl().
 			SetBaseURL(ts.URL+"/").
 			SetDigestAuth(conf.username, conf.password)
 
@@ -162,7 +162,7 @@ func TestOnAfterMiddleware(t *testing.T) {
 	ts := createGenericServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.OnAfterResponse(func(c *Client, res *Response) error {
 		t.Logf("Request sent at: %v", res.Request.Time)
 		t.Logf("Response Received at: %v", res.ReceivedAt())
@@ -183,7 +183,7 @@ func TestClientRedirectPolicy(t *testing.T) {
 	ts := createRedirectServer(t)
 	defer ts.Close()
 
-	c := dc().SetRedirectPolicy(FlexibleRedirectPolicy(20))
+	c := dcnl().SetRedirectPolicy(FlexibleRedirectPolicy(20))
 	_, err := c.R().Get(ts.URL + "/redirect-1")
 
 	assertEqual(t, true, (err.Error() == "Get /redirect-21: stopped after 20 redirects" ||
@@ -199,7 +199,7 @@ func TestClientTimeout(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc().SetTimeout(time.Second * 3)
+	c := dcnl().SetTimeout(time.Second * 3)
 	_, err := c.R().Get(ts.URL + "/set-timeout-test")
 
 	assertEqual(t, true, strings.Contains(strings.ToLower(err.Error()), "timeout"))
@@ -209,7 +209,7 @@ func TestClientTimeoutWithinThreshold(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc().SetTimeout(time.Second * 3)
+	c := dcnl().SetTimeout(time.Second * 3)
 	resp, err := c.R().Get(ts.URL + "/set-timeout-test-with-sequence")
 
 	assertError(t, err)
@@ -225,7 +225,7 @@ func TestClientTimeoutWithinThreshold(t *testing.T) {
 }
 
 func TestClientTimeoutInternalError(t *testing.T) {
-	c := dc().SetTimeout(time.Second * 1)
+	c := dcnl().SetTimeout(time.Second * 1)
 	_, _ = c.R().Get("http://localhost:9000/set-timeout-test")
 }
 
@@ -233,7 +233,7 @@ func TestClientProxy(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetTimeout(1 * time.Second)
 	c.SetProxy("http://sampleproxy:8888")
 
@@ -251,7 +251,7 @@ func TestClientProxy(t *testing.T) {
 }
 
 func TestClientSetCertificates(t *testing.T) {
-	client := dc()
+	client := dcnl()
 	client.SetCertificates(tls.Certificate{})
 
 	transport, err := client.Transport()
@@ -261,57 +261,78 @@ func TestClientSetCertificates(t *testing.T) {
 }
 
 func TestClientSetRootCertificate(t *testing.T) {
-	client := dc()
-	client.SetRootCertificate(filepath.Join(getTestDataPath(), "sample-root.pem"))
+	t.Run("root cert", func(t *testing.T) {
+		client := dcnl()
+		client.SetRootCertificate(filepath.Join(getTestDataPath(), "sample-root.pem"))
 
-	transport, err := client.Transport()
+		transport, err := client.Transport()
 
-	assertNil(t, err)
-	assertNotNil(t, transport.TLSClientConfig.RootCAs)
-}
+		assertNil(t, err)
+		assertNotNil(t, transport.TLSClientConfig.RootCAs)
+	})
 
-func TestClientSetRootCertificateNotExists(t *testing.T) {
-	client := dc()
-	client.SetRootCertificate(filepath.Join(getTestDataPath(), "not-exists-sample-root.pem"))
+	t.Run("root cert not exists", func(t *testing.T) {
+		client := dcnl()
+		client.SetRootCertificate(filepath.Join(getTestDataPath(), "not-exists-sample-root.pem"))
 
-	transport, err := client.Transport()
+		transport, err := client.Transport()
 
-	assertNil(t, err)
-	assertNil(t, transport.TLSClientConfig)
-}
+		assertNil(t, err)
+		assertNil(t, transport.TLSClientConfig)
+	})
 
-func TestClientSetRootCertificateFromString(t *testing.T) {
-	client := dc()
-	rootPemData, err := os.ReadFile(filepath.Join(getTestDataPath(), "sample-root.pem"))
-	assertNil(t, err)
+	t.Run("root cert from string", func(t *testing.T) {
+		client := dcnl()
+		rootPemData, err := os.ReadFile(filepath.Join(getTestDataPath(), "sample-root.pem"))
+		assertNil(t, err)
 
-	client.SetRootCertificateFromString(string(rootPemData))
+		client.SetRootCertificateFromString(string(rootPemData))
 
-	transport, err := client.Transport()
+		transport, err := client.Transport()
 
-	assertNil(t, err)
-	assertNotNil(t, transport.TLSClientConfig.RootCAs)
+		assertNil(t, err)
+		assertNotNil(t, transport.TLSClientConfig.RootCAs)
+	})
 }
 
-func TestClientSetRootCertificateFromStringErrorTls(t *testing.T) {
-	client := NewWithClient(&http.Client{})
-	client.outputLogTo(io.Discard)
+func TestClientCACertificateFromStringErrorTls(t *testing.T) {
+	t.Run("root cert string", func(t *testing.T) {
+		client := NewWithClient(&http.Client{})
+		client.outputLogTo(io.Discard)
 
-	rootPemData, err := os.ReadFile(filepath.Join(getTestDataPath(), "sample-root.pem"))
-	assertNil(t, err)
-	rt := &CustomRoundTripper{}
-	client.SetTransport(rt)
-	transport, err := client.Transport()
+		rootPemData, err := os.ReadFile(filepath.Join(getTestDataPath(), "sample-root.pem"))
+		assertNil(t, err)
+		rt := &CustomRoundTripper{}
+		client.SetTransport(rt)
+		transport, err := client.Transport()
 
-	client.SetRootCertificateFromString(string(rootPemData))
+		client.SetRootCertificateFromString(string(rootPemData))
 
-	assertNotNil(t, rt)
-	assertNotNil(t, err)
-	assertNil(t, transport)
+		assertNotNil(t, rt)
+		assertNotNil(t, err)
+		assertNil(t, transport)
+	})
+
+	t.Run("client cert string", func(t *testing.T) {
+		client := NewWithClient(&http.Client{})
+		client.outputLogTo(io.Discard)
+
+		rootPemData, err := os.ReadFile(filepath.Join(getTestDataPath(), "sample-root.pem"))
+		assertNil(t, err)
+		rt := &CustomRoundTripper{}
+		client.SetTransport(rt)
+		transport, err := client.Transport()
+
+		client.SetClientRootCertificateFromString(string(rootPemData))
+
+		assertNotNil(t, rt)
+		assertNotNil(t, err)
+		assertNil(t, transport)
+	})
 }
 
 func TestClientSetClientRootCertificate(t *testing.T) {
-	client := dc()
+	client := dcnl()
 	client.SetClientRootCertificate(filepath.Join(getTestDataPath(), "sample-root.pem"))
 
 	transport, err := client.Transport()
@@ -321,7 +342,7 @@ func TestClientSetClientRootCertificate(t *testing.T) {
 }
 
 func TestClientSetClientRootCertificateNotExists(t *testing.T) {
-	client := dc()
+	client := dcnl()
 	client.SetClientRootCertificate(filepath.Join(getTestDataPath(), "not-exists-sample-root.pem"))
 
 	transport, err := client.Transport()
@@ -331,7 +352,7 @@ func TestClientSetClientRootCertificateNotExists(t *testing.T) {
 }
 
 func TestClientSetClientRootCertificateFromString(t *testing.T) {
-	client := dc()
+	client := dcnl()
 	rootPemData, err := os.ReadFile(filepath.Join(getTestDataPath(), "sample-root.pem"))
 	assertNil(t, err)
 
@@ -343,25 +364,8 @@ func TestClientSetClientRootCertificateFromString(t *testing.T) {
 	assertNotNil(t, transport.TLSClientConfig.ClientCAs)
 }
 
-func TestClientSetClientRootCertificateFromStringErrorTls(t *testing.T) {
-	client := NewWithClient(&http.Client{})
-	client.outputLogTo(io.Discard)
-
-	rootPemData, err := os.ReadFile(filepath.Join(getTestDataPath(), "sample-root.pem"))
-	assertNil(t, err)
-	rt := &CustomRoundTripper{}
-	client.SetTransport(rt)
-	transport, err := client.Transport()
-
-	client.SetClientRootCertificateFromString(string(rootPemData))
-
-	assertNotNil(t, rt)
-	assertNotNil(t, err)
-	assertNil(t, transport)
-}
-
 func TestClientOnBeforeRequestModification(t *testing.T) {
-	tc := dc()
+	tc := dcnl()
 	tc.OnBeforeRequest(func(c *Client, r *Request) error {
 		r.SetAuthToken("This is test auth token")
 		return nil
@@ -385,7 +389,7 @@ func TestClientSetHeaderVerbatim(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	c := dc().
+	c := dcnl().
 		SetHeaderVerbatim("header-lowercase", "value_lowercase").
 		SetHeader("header-lowercase", "value_standard")
 
@@ -398,7 +402,7 @@ func TestClientSetHeaderVerbatim(t *testing.T) {
 func TestClientSetTransport(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
-	client := dc()
+	client := dcnl()
 
 	transport := &http.Transport{
 		// something like Proxying to httptest.Server, etc...
@@ -414,7 +418,7 @@ func TestClientSetTransport(t *testing.T) {
 }
 
 func TestClientSetScheme(t *testing.T) {
-	client := dc()
+	client := dcnl()
 
 	client.SetScheme("http")
 
@@ -422,7 +426,7 @@ func TestClientSetScheme(t *testing.T) {
 }
 
 func TestClientSetCookieJar(t *testing.T) {
-	client := dc()
+	client := dcnl()
 	backupJar := client.httpClient.Jar
 
 	client.SetCookieJar(nil)
@@ -435,7 +439,7 @@ func TestClientSetCookieJar(t *testing.T) {
 // This test methods exist for test coverage purpose
 // to validate the getter and setter
 func TestClientSettingsCoverage(t *testing.T) {
-	c := dc()
+	c := dcnl()
 
 	assertNotNil(t, c.CookieJar())
 	assertNotNil(t, c.ContentTypeEncoders())
@@ -458,8 +462,10 @@ func TestClientSettingsCoverage(t *testing.T) {
 
 	c.SetCloseConnection(true)
 
+	c.DisableDebug()
+
 	// [Start] Custom Transport scenario
-	ct := dc()
+	ct := dcnl()
 	ct.SetTransport(&CustomRoundTripper{})
 	_, err := ct.Transport()
 	assertNotNil(t, err)
@@ -470,13 +476,14 @@ func TestClientSettingsCoverage(t *testing.T) {
 
 	ct.SetCertificates(tls.Certificate{})
 	ct.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})
+	ct.SetRootCertificateFromString("root cert")
 
 	ct.outputLogTo(io.Discard)
 	// [End] Custom Transport scenario
 }
 
 func TestContentLengthWhenBodyIsNil(t *testing.T) {
-	client := dc()
+	client := dcnl()
 
 	client.SetPreRequestHook(func(c *Client, r *http.Request) error {
 		assertEqual(t, "0", r.Header.Get(hdrContentLengthKey))
@@ -487,7 +494,7 @@ func TestContentLengthWhenBodyIsNil(t *testing.T) {
 }
 
 func TestClientPreRequestHook(t *testing.T) {
-	client := dc()
+	client := dcnl()
 	client.SetPreRequestHook(func(c *Client, r *http.Request) error {
 		c.log.Debugf("I'm in Pre-Request Hook")
 		return nil
@@ -529,7 +536,7 @@ func TestClientAllowsGetMethodPayload(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetAllowGetMethodPayload(true)
 	c.SetPreRequestHook(func(*Client, *http.Request) error { return nil }) // for coverage
 
@@ -545,7 +552,7 @@ func TestClientAllowsGetMethodPayloadIoReader(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetAllowGetMethodPayload(true)
 
 	payload := "test-payload"
@@ -561,7 +568,7 @@ func TestClientAllowsGetMethodPayloadDisabled(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetAllowGetMethodPayload(false)
 
 	payload := bytes.NewReader([]byte("test-payload"))
@@ -595,36 +602,36 @@ func TestDebugBodySizeLimit(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc().
-		SetDebug(true).
-		SetDebugBodyLimit(30)
-
-	var lgr bytes.Buffer
-	c.outputLogTo(&lgr) // internal method
+	c, lb := dcld()
+	c.SetDebugBodyLimit(30)
 
-	testcases := []struct{ url, want string }{
+	testcases := []struct{ url, want, wantErr string }{
 		// Text, does not exceed limit.
-		{ts.URL, "TestGet: text response"},
+		{url: ts.URL, want: "TestGet: text response"},
 		// Empty response.
-		{ts.URL + "/no-content", "***** NO CONTENT *****"},
+		{url: ts.URL + "/no-content", want: "***** NO CONTENT *****"},
 		// JSON, does not exceed limit.
-		{ts.URL + "/json", "{\n   \"TestGet\": \"JSON response\"\n}"},
+		{url: ts.URL + "/json", want: "{\n   \"TestGet\": \"JSON response\"\n}"},
 		// Invalid JSON, does not exceed limit.
-		{ts.URL + "/json-invalid", "TestGet: Invalid JSON"},
+		{url: ts.URL + "/json-invalid", wantErr: "invalid character 'T' looking for beginning of value"},
 		// Text, exceeds limit.
-		{ts.URL + "/long-text", "RESPONSE TOO LARGE"},
+		{url: ts.URL + "/long-text", want: "RESPONSE TOO LARGE"},
 		// JSON, exceeds limit.
-		{ts.URL + "/long-json", "RESPONSE TOO LARGE"},
+		{url: ts.URL + "/long-json", want: "RESPONSE TOO LARGE"},
 	}
-
 	for _, tc := range testcases {
 		_, err := c.R().Get(tc.url)
-		assertError(t, err)
-		debugLog := lgr.String()
-		if !strings.Contains(debugLog, tc.want) {
-			t.Errorf("Expected logs to contain [%v], got [\n%v]", tc.want, debugLog)
+		if tc.wantErr != "" {
+			assertNotNil(t, err)
+			assertEqual(t, tc.wantErr, err.Error())
+		} else if tc.want != "" {
+			assertError(t, err)
+			debugLog := lb.String()
+			if !strings.Contains(debugLog, tc.want) {
+				t.Errorf("Expected logs to contain [%v], got [\n%v]", tc.want, debugLog)
+			}
+			lb.Reset()
 		}
-		lgr.Reset()
 	}
 }
 
@@ -666,10 +673,7 @@ func TestLogCallbacks(t *testing.T) {
 	ts := createAuthServer(t)
 	defer ts.Close()
 
-	c := New().SetDebug(true)
-
-	var lgr bytes.Buffer
-	c.outputLogTo(&lgr)
+	c, lb := dcld()
 
 	c.OnRequestLog(func(r *RequestLog) error {
 		// masking authorization header
@@ -693,7 +697,7 @@ func TestLogCallbacks(t *testing.T) {
 	assertEqual(t, http.StatusOK, resp.StatusCode())
 
 	// Validating debug log updates
-	logInfo := lgr.String()
+	logInfo := lb.String()
 	assertEqual(t, true, strings.Contains(logInfo, "Bearer *******************************"))
 	assertEqual(t, true, strings.Contains(logInfo, "X-Debug-Response-Log"))
 	assertEqual(t, true, strings.Contains(logInfo, "Modified the response body content"))
@@ -719,10 +723,9 @@ func TestLogCallbacks(t *testing.T) {
 func TestDebugLogSimultaneously(t *testing.T) {
 	ts := createGetServer(t)
 
-	c := New().
+	c := dcnl().
 		SetDebug(true).
-		SetBaseURL(ts.URL).
-		outputLogTo(io.Discard)
+		SetBaseURL(ts.URL)
 
 	t.Cleanup(ts.Close)
 	for i := 0; i < 50; i++ {
@@ -921,7 +924,7 @@ func TestClientOnResponseError(t *testing.T) {
 					assertEqual(t, 1, hook6)
 				}
 			}()
-			c := New().outputLogTo(io.Discard).
+			c := dcnl().
 				SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}).
 				SetAuthToken("004DDB79-6801-4587-B976-F093E6AC44FF").
 				SetRetryCount(0).
@@ -1009,7 +1012,7 @@ func TestHostURLForGH318AndGH407(t *testing.T) {
 	// test the functionality with httpbin.org locally
 	// will figure out later
 
-	c := dc()
+	c := dcnl()
 	// c.SetScheme("http")
 	// c.SetHostURL(targetURL.Host + "/")
 
@@ -1040,7 +1043,7 @@ func TestPostRedirectWithBody(t *testing.T) {
 	t.Log("ts.URL:", ts.URL)
 	t.Log("targetURL.Host:", targetURL.Host)
 
-	c := dc()
+	c := dcnl()
 	wg := sync.WaitGroup{}
 	for i := 0; i < 100; i++ {
 		wg.Add(1)
@@ -1115,7 +1118,7 @@ func TestResponseBodyLimit(t *testing.T) {
 	defer ts.Close()
 
 	t.Run("Client body limit", func(t *testing.T) {
-		c := dc().SetResponseBodyLimit(1024)
+		c := dcnl().SetResponseBodyLimit(1024)
 		assertEqual(t, int64(1024), c.ResponseBodyLimit())
 		resp, err := c.R().Get(ts.URL + "/")
 		assertNotNil(t, err)
@@ -1124,7 +1127,7 @@ func TestResponseBodyLimit(t *testing.T) {
 	})
 
 	t.Run("request body limit", func(t *testing.T) {
-		c := dc()
+		c := dcnl()
 
 		resp, err := c.R().SetResponseBodyLimit(1024).Get(ts.URL + "/")
 		assertNotNil(t, err)
@@ -1133,7 +1136,7 @@ func TestResponseBodyLimit(t *testing.T) {
 	})
 
 	t.Run("body less than limit", func(t *testing.T) {
-		c := dc()
+		c := dcnl()
 
 		res, err := c.R().SetResponseBodyLimit(800*100 + 10).Get(ts.URL + "/")
 		assertNil(t, err)
@@ -1142,7 +1145,7 @@ func TestResponseBodyLimit(t *testing.T) {
 	})
 
 	t.Run("no body limit", func(t *testing.T) {
-		c := dc()
+		c := dcnl()
 
 		res, err := c.R().Get(ts.URL + "/")
 		assertNil(t, err)
@@ -1158,7 +1161,7 @@ func TestResponseBodyLimit(t *testing.T) {
 		})
 		defer tse.Close()
 
-		c := dc()
+		c := dcnl()
 
 		_, err := c.R().SetResponseBodyLimit(10240).Get(tse.URL + "/")
 		assertErrorIs(t, gzip.ErrHeader, err)
diff --git a/context_test.go b/context_test.go
index 378358a..5483039 100644
--- a/context_test.go
+++ b/context_test.go
@@ -20,7 +20,7 @@ func TestSetContext(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	resp, err := dc().R().
+	resp, err := dcnl().R().
 		SetContext(context.Background()).
 		Get(ts.URL + "/")
 
@@ -37,7 +37,7 @@ func TestSetContextWithError(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	resp, err := dcr().
+	resp, err := dcnlr().
 		SetContext(context.Background()).
 		Get(ts.URL + "/mypage")
 
@@ -71,7 +71,7 @@ func TestSetContextCancel(t *testing.T) {
 		cancel()
 	}()
 
-	_, err := dc().R().
+	_, err := dcnl().R().
 		SetContext(ctx).
 		Get(ts.URL + "/")
 
@@ -110,7 +110,7 @@ func TestSetContextCancelRetry(t *testing.T) {
 		cancel()
 	}()
 
-	c := dc().
+	c := dcnl().
 		SetTimeout(time.Second * 3).
 		SetRetryCount(3)
 
@@ -157,7 +157,7 @@ func TestSetContextCancelWithError(t *testing.T) {
 		cancel()
 	}()
 
-	_, err := dc().R().
+	_, err := dcnl().R().
 		SetContext(ctx).
 		Get(ts.URL + "/")
 
@@ -184,7 +184,7 @@ func TestClientRetryWithSetContext(t *testing.T) {
 	})
 	defer ts.Close()
 
-	c := dc().
+	c := dcnl().
 		SetTimeout(time.Second * 1).
 		SetRetryCount(3)
 
@@ -199,7 +199,7 @@ func TestClientRetryWithSetContext(t *testing.T) {
 }
 
 func TestRequestContext(t *testing.T) {
-	client := dc()
+	client := dcnl()
 	r := client.NewRequest()
 	assertNotNil(t, r.Context())
 
diff --git a/curl_cmd_test.go b/curl_cmd_test.go
index 0784fbf..79754b8 100644
--- a/curl_cmd_test.go
+++ b/curl_cmd_test.go
@@ -10,7 +10,7 @@ import (
 
 // 1. Generate curl for unexecuted request(dry-run)
 func TestGenerateUnexecutedCurl(t *testing.T) {
-	req := dclr().
+	req := dcnldr().
 		SetBody(map[string]string{
 			"name": "Alex",
 		}).
@@ -18,7 +18,8 @@ func TestGenerateUnexecutedCurl(t *testing.T) {
 			[]*http.Cookie{
 				{Name: "count", Value: "1"},
 			},
-		)
+		).
+		SetMethod(MethodPost)
 
 	assertEqual(t, "", req.GenerateCurlCommand())
 
@@ -26,7 +27,7 @@ func TestGenerateUnexecutedCurl(t *testing.T) {
 	req.DisableGenerateCurlOnDebug()
 
 	if !strings.Contains(curlCmdUnexecuted, "Cookie: count=1") ||
-		!strings.Contains(curlCmdUnexecuted, "curl -X GET") ||
+		!strings.Contains(curlCmdUnexecuted, "curl -X POST") ||
 		!strings.Contains(curlCmdUnexecuted, `-d '{"name":"Alex"}'`) {
 		t.Fatal("Incomplete curl:", curlCmdUnexecuted)
 	} else {
@@ -43,7 +44,7 @@ func TestGenerateExecutedCurl(t *testing.T) {
 	data := map[string]string{
 		"name": "Alex",
 	}
-	c := dcl()
+	c := dcnl().EnableDebug()
 	req := c.R().
 		SetBody(data).
 		SetCookies(
@@ -114,6 +115,13 @@ func TestDebugModeCurl(t *testing.T) {
 	}
 }
 
+func TestCurlMiscTestCoverage(t *testing.T) {
+	cookieStr := dumpCurlCookies([]*http.Cookie{
+		{Name: "count", Value: "1"},
+	})
+	assertEqual(t, "Cookie: count=1", cookieStr)
+}
+
 func captureStderr() (getOutput func() string, restore func()) {
 	old := os.Stderr
 	r, w, err := os.Pipe()
diff --git a/request_test.go b/request_test.go
index 435943d..372328c 100644
--- a/request_test.go
+++ b/request_test.go
@@ -36,7 +36,7 @@ func TestGet(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	resp, err := dc().R().
+	resp, err := dcnl().R().
 		SetQueryParam("request_no", strconv.FormatInt(time.Now().Unix(), 10)).
 		Get(ts.URL + "/")
 
@@ -54,7 +54,7 @@ func TestGetGH524(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	resp, err := dc().R().
+	resp, err := dcnl().R().
 		SetPathParams((map[string]string{
 			"userId":       "sample@sample.com",
 			"subAccountId": "100002",
@@ -76,7 +76,7 @@ func TestRateLimiter(t *testing.T) {
 	// Test a burst with a valid capacity and then a consecutive request that must fail.
 
 	// Allow a rate of 1 every 100 ms but also allow bursts of 10 requests.
-	client := dc().SetRateLimiter(rate.NewLimiter(rate.Every(100*time.Millisecond), 10))
+	client := dcnl().SetRateLimiter(rate.NewLimiter(rate.Every(100*time.Millisecond), 10))
 
 	// Execute a burst of 10 requests.
 	for i := 0; i < 10; i++ {
@@ -95,7 +95,7 @@ func TestRateLimiter(t *testing.T) {
 	// Test continues request at a valid rate
 
 	// Allow a rate of 1 every ms with no burst.
-	client = dc().SetRateLimiter(rate.NewLimiter(rate.Every(1*time.Millisecond), 1))
+	client = dcnl().SetRateLimiter(rate.NewLimiter(rate.Every(1*time.Millisecond), 1))
 
 	// Sending requests every ms+tiny delta must succeed.
 	for i := 0; i < 100; i++ {
@@ -111,7 +111,7 @@ func TestIllegalRetryCount(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	resp, err := dc().SetRetryCount(-1).R().Get(ts.URL + "/")
+	resp, err := dcnl().SetRetryCount(-1).R().Get(ts.URL + "/")
 
 	assertNil(t, err)
 	assertNil(t, resp)
@@ -121,7 +121,7 @@ func TestGetCustomUserAgent(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	resp, err := dcr().
+	resp, err := dcnlr().
 		SetHeader(hdrUserAgentKey, "Test Custom User agent").
 		SetQueryParam("request_no", strconv.FormatInt(time.Now().Unix(), 10)).
 		Get(ts.URL + "/")
@@ -139,7 +139,7 @@ func TestGetClientParamRequestParam(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetQueryParam("client_param", "true").
 		SetQueryParams(map[string]string{"req_1": "jeeva", "req_3": "jeeva3"}).
 		SetDebug(true)
@@ -164,7 +164,7 @@ func TestGetRelativePath(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetBaseURL(ts.URL)
 
 	resp, err := c.R().Get("mypage2")
@@ -180,7 +180,7 @@ func TestGet400Error(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	resp, err := dcr().Get(ts.URL + "/mypage")
+	resp, err := dcnlr().Get(ts.URL + "/mypage")
 
 	assertError(t, err)
 	assertEqual(t, http.StatusBadRequest, resp.StatusCode())
@@ -193,7 +193,7 @@ func TestPostJSONStringSuccess(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetHeader(hdrContentTypeKey, "application/json; charset=utf-8").
 		SetHeaders(map[string]string{hdrUserAgentKey: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) go-resty v0.1", hdrAcceptKey: "application/json; charset=utf-8"})
 
@@ -221,7 +221,7 @@ func TestPostJSONBytesSuccess(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetHeader(hdrContentTypeKey, "application/json; charset=utf-8").
 		SetHeaders(map[string]string{hdrUserAgentKey: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) go-resty v0.7", hdrAcceptKey: "application/json; charset=utf-8"})
 
@@ -239,7 +239,7 @@ func TestPostJSONBytesIoReader(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetHeader(hdrContentTypeKey, "application/json; charset=utf-8")
 
 	bodyBytes := []byte(`{"username":"testuser", "password":"testpass"}`)
@@ -260,7 +260,7 @@ func TestPostJSONStructSuccess(t *testing.T) {
 
 	user := &User{Username: "testuser", Password: "testpass"}
 
-	c := dc().SetJSONEscapeHTML(false)
+	c := dcnl().SetJSONEscapeHTML(false)
 	resp, err := c.R().
 		SetHeader(hdrContentTypeKey, "application/json; charset=utf-8").
 		SetBody(user).
@@ -282,7 +282,7 @@ func TestPostJSONRPCStructSuccess(t *testing.T) {
 
 	user := &User{Username: "testuser", Password: "testpass"}
 
-	c := dc().SetJSONEscapeHTML(false)
+	c := dcnl().SetJSONEscapeHTML(false)
 	resp, err := c.R().
 		SetHeader(hdrContentTypeKey, "application/json-rpc").
 		SetBody(user).
@@ -303,7 +303,7 @@ func TestPostJSONStructInvalidLogin(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetDebug(false)
 
 	resp, err := c.R().
@@ -328,7 +328,7 @@ func TestPostJSONErrorRFC7807(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	resp, err := c.R().
 		SetHeader(hdrContentTypeKey, "application/json; charset=utf-8").
 		SetBody(User{Username: "testuser", Password: "testpass1"}).
@@ -350,7 +350,7 @@ func TestPostJSONMapSuccess(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetDebug(false)
 
 	resp, err := c.R().
@@ -370,7 +370,7 @@ func TestPostJSONMapInvalidResponseJson(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetBody(map[string]any{"username": "testuser", "password": "invalidjson"}).
 		SetResult(&AuthSuccess{}).
 		Post(ts.URL + "/login")
@@ -400,7 +400,7 @@ func TestPostJSONMarshalError(t *testing.T) {
 	b := brokenMarshalJSON{}
 	exp := "b0rk3d"
 
-	_, err := dclr().
+	_, err := dcnldr().
 		SetHeader(hdrContentTypeKey, "application/json").
 		SetBody(b).
 		Post(ts.URL + "/login")
@@ -418,7 +418,7 @@ func TestForceContentTypeForGH276andGH240(t *testing.T) {
 	defer ts.Close()
 
 	retried := 0
-	c := dc()
+	c := dcnl()
 	c.SetDebug(false)
 	c.SetRetryCount(3)
 	c.SetRetryAfter(RetryAfterFunc(func(*Client, *Response) (time.Duration, error) {
@@ -446,7 +446,7 @@ func TestPostXMLStringSuccess(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetDebug(false)
 
 	resp, err := c.R().
@@ -475,7 +475,7 @@ func TestPostXMLMarshalError(t *testing.T) {
 	b := brokenMarshalXML{}
 	exp := "b0rk3d"
 
-	_, err := dclr().
+	_, err := dcnldr().
 		SetHeader(hdrContentTypeKey, "application/xml").
 		SetBody(b).
 		Post(ts.URL + "/login")
@@ -492,7 +492,7 @@ func TestPostXMLStringError(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetHeader(hdrContentTypeKey, "application/xml").
 		SetBody(`<?xml version="1.0" encoding="UTF-8"?><User><Username>testuser</Username>testpass</Password></User>`).
 		Post(ts.URL + "/login")
@@ -508,7 +508,7 @@ func TestPostXMLBytesSuccess(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetDebug(false)
 
 	resp, err := c.R().
@@ -528,7 +528,7 @@ func TestPostXMLStructSuccess(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetHeader(hdrContentTypeKey, "application/xml").
 		SetBody(User{Username: "testuser", Password: "testpass"}).
 		SetContentLength(true).
@@ -547,7 +547,7 @@ func TestPostXMLStructInvalidLogin(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetError(&AuthError{})
 
 	resp, err := c.R().
@@ -568,7 +568,7 @@ func TestPostXMLStructInvalidResponseXml(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetHeader(hdrContentTypeKey, "application/xml").
 		SetBody(User{Username: "testuser", Password: "invalidxml"}).
 		SetResult(&AuthSuccess{}).
@@ -586,7 +586,7 @@ func TestPostXMLMapNotSupported(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	_, err := dclr().
+	_, err := dcnldr().
 		SetHeader(hdrContentTypeKey, "application/xml").
 		SetBody(map[string]any{"Username": "testuser", "Password": "testpass"}).
 		Post(ts.URL + "/login")
@@ -598,7 +598,7 @@ func TestRequestBasicAuth(t *testing.T) {
 	ts := createAuthServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetBaseURL(ts.URL).
 		SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})
 
@@ -618,7 +618,7 @@ func TestRequestBasicAuthWithBody(t *testing.T) {
 	ts := createAuthServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetBaseURL(ts.URL).
 		SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})
 
@@ -643,7 +643,7 @@ func TestRequestInsecureBasicAuth(t *testing.T) {
 	logger := createLogger()
 	logger.l.SetOutput(&logBuf)
 
-	c := dc()
+	c := dcnl()
 	c.SetBaseURL(ts.URL)
 
 	resp, err := c.R().
@@ -665,7 +665,7 @@ func TestRequestBasicAuthFail(t *testing.T) {
 	ts := createAuthServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}).
 		SetError(AuthError{})
 
@@ -684,7 +684,7 @@ func TestRequestAuthToken(t *testing.T) {
 	ts := createAuthServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}).
 		SetAuthToken("004DDB79-6801-4587-B976-F093E6AC44FF")
 
@@ -700,7 +700,7 @@ func TestRequestAuthScheme(t *testing.T) {
 	ts := createAuthServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}).
 		SetAuthScheme("OAuth").
 		SetAuthToken("004DDB79-6801-4587-B976-F093E6AC44FF")
@@ -719,7 +719,7 @@ func TestRequestDigestAuth(t *testing.T) {
 	ts := createDigestServer(t, nil)
 	defer ts.Close()
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetDigestAuth(conf.username, conf.password).
 		SetResult(&AuthSuccess{}).
 		Get(ts.URL + conf.uri)
@@ -736,7 +736,7 @@ func TestRequestDigestAuthFail(t *testing.T) {
 	ts := createDigestServer(t, nil)
 	defer ts.Close()
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetDigestAuth(conf.username, "wrongPassword").
 		SetError(AuthError{}).
 		Get(ts.URL + conf.uri)
@@ -753,7 +753,7 @@ func TestRequestDigestAuthWithBody(t *testing.T) {
 	ts := createDigestServer(t, nil)
 	defer ts.Close()
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetDigestAuth(conf.username, conf.password).
 		SetResult(&AuthSuccess{}).
 		SetHeader(hdrContentTypeKey, "application/json").
@@ -771,7 +771,7 @@ func TestFormData(t *testing.T) {
 	ts := createFormPostServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetFormData(map[string]string{"zip_code": "00000", "city": "Los Angeles"}).
 		SetContentLength(true).
 		SetDebug(true)
@@ -795,7 +795,7 @@ func TestMultiValueFormData(t *testing.T) {
 		"search_criteria": []string{"book", "glass", "pencil"},
 	}
 
-	c := dc()
+	c := dcnl()
 	c.SetContentLength(true).SetDebug(true)
 	c.outputLogTo(io.Discard)
 
@@ -812,7 +812,7 @@ func TestFormDataDisableWarn(t *testing.T) {
 	ts := createFormPostServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetFormData(map[string]string{"zip_code": "00000", "city": "Los Angeles"}).
 		SetContentLength(true).
 		SetDisableWarn(true)
@@ -836,7 +836,7 @@ func TestMultiPartUploadFile(t *testing.T) {
 
 	basePath := getTestDataPath()
 
-	c := dc()
+	c := dcnl()
 	c.SetFormData(map[string]string{"zip_code": "00001", "city": "Los Angeles"})
 
 	resp, err := c.R().
@@ -855,7 +855,7 @@ func TestMultiPartUploadFileViaPatch(t *testing.T) {
 
 	basePath := getTestDataPath()
 
-	c := dc()
+	c := dcnl()
 	c.SetFormData(map[string]string{"zip_code": "00001", "city": "Los Angeles"})
 
 	resp, err := c.R().
@@ -874,7 +874,7 @@ func TestMultiPartUploadFileError(t *testing.T) {
 
 	basePath := getTestDataPath()
 
-	c := dc()
+	c := dcnl()
 	c.SetFormData(map[string]string{"zip_code": "00001", "city": "Los Angeles"})
 
 	resp, err := c.R().
@@ -896,7 +896,7 @@ func TestMultiPartUploadFiles(t *testing.T) {
 
 	basePath := getTestDataPath()
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetFormDataFromValues(url.Values{
 			"first_name": []string{"Jeevanandam"},
 			"last_name":  []string{"M"},
@@ -929,7 +929,7 @@ func TestMultiPartIoReaderFiles(t *testing.T) {
 	}
 	t.Logf("File Info: %v", file.String())
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetFormData(map[string]string{"first_name": "Jeevanandam", "last_name": "M"}).
 		SetFileReader("profile_img", "test-img.png", bytes.NewReader(profileImgBytes)).
 		SetFileReader("notes", "text-file.txt", bytes.NewReader(notesBytes)).
@@ -950,13 +950,13 @@ func TestMultiPartUploadFileNotOnGetOrDelete(t *testing.T) {
 
 	basePath := getTestDataPath()
 
-	_, err := dclr().
+	_, err := dcnldr().
 		SetFile("profile_img", filepath.Join(basePath, "test-img.png")).
 		Get(ts.URL + "/upload")
 
 	assertEqual(t, "multipart content is not allowed in HTTP verb [GET]", err.Error())
 
-	_, err = dclr().
+	_, err = dcnldr().
 		SetFile("profile_img", filepath.Join(basePath, "test-img.png")).
 		Delete(ts.URL + "/upload")
 
@@ -964,7 +964,7 @@ func TestMultiPartUploadFileNotOnGetOrDelete(t *testing.T) {
 
 	var hook1Count int
 	var hook2Count int
-	_, err = dc().
+	_, err = dcnl().
 		OnInvalid(func(r *Request, err error) {
 			assertEqual(t, "multipart content is not allowed in HTTP verb [HEAD]", err.Error())
 			assertNotNil(t, r)
@@ -987,7 +987,7 @@ func TestMultiPartUploadFileNotOnGetOrDelete(t *testing.T) {
 func TestMultiPartFormData(t *testing.T) {
 	ts := createFormPostServer(t)
 	defer ts.Close()
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetMultipartFormData(map[string]string{"first_name": "Jeevanandam", "last_name": "M", "zip_code": "00001"}).
 		SetBasicAuth("myuser", "mypass").
 		Post(ts.URL + "/profile")
@@ -1004,7 +1004,7 @@ func TestMultiPartMultipartField(t *testing.T) {
 
 	jsonBytes := []byte(`{"input": {"name": "Uploaded document", "_filename" : ["file.txt"]}}`)
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetFormDataFromValues(url.Values{
 			"first_name": []string{"Jeevanandam"},
 			"last_name":  []string{"M"},
@@ -1047,7 +1047,7 @@ func TestMultiPartMultipartFields(t *testing.T) {
 		},
 	}
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetFormData(map[string]string{"first_name": "Jeevanandam", "last_name": "M"}).
 		SetMultipartFields(fields...).
 		Post(ts.URL + "/upload")
@@ -1065,7 +1065,7 @@ func TestMultiPartCustomBoundary(t *testing.T) {
 	defer ts.Close()
 	defer cleanupFiles(".testdata/upload")
 
-	_, err := dclr().
+	_, err := dcnldr().
 		SetMultipartFormData(map[string]string{"first_name": "Jeevanandam", "last_name": "M", "zip_code": "00001"}).
 		SetMultipartBoundary(`"my-custom-boundary"`).
 		SetBasicAuth("myuser", "mypass").
@@ -1073,7 +1073,7 @@ func TestMultiPartCustomBoundary(t *testing.T) {
 
 	assertEqual(t, "mime: invalid boundary character", err.Error())
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetMultipartFormData(map[string]string{"first_name": "Jeevanandam", "last_name": "M", "zip_code": "00001"}).
 		SetMultipartBoundary("my-custom-boundary").
 		Post(ts.URL + "/profile")
@@ -1087,7 +1087,7 @@ func TestGetWithCookie(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dcl()
+	c := dcnl()
 	c.SetBaseURL(ts.URL)
 	c.SetCookie(&http.Cookie{
 		Name:  "go-resty-1",
@@ -1118,7 +1118,7 @@ func TestGetWithCookies(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetBaseURL(ts.URL).SetDebug(true)
 
 	tu, _ := url.Parse(ts.URL)
@@ -1167,7 +1167,7 @@ func TestPutPlainString(t *testing.T) {
 	ts := createGenericServer(t)
 	defer ts.Close()
 
-	resp, err := dc().R().
+	resp, err := dcnl().R().
 		SetBody("This is plain text body to server").
 		Put(ts.URL + "/plaintext")
 
@@ -1180,7 +1180,7 @@ func TestPutJSONString(t *testing.T) {
 	ts := createGenericServer(t)
 	defer ts.Close()
 
-	client := dc()
+	client := dcnl()
 
 	client.OnBeforeRequest(func(c *Client, r *Request) error {
 		r.SetHeader("X-Custom-Request-Middleware", "OnBeforeRequest middleware")
@@ -1209,7 +1209,7 @@ func TestPutXMLString(t *testing.T) {
 	ts := createGenericServer(t)
 	defer ts.Close()
 
-	resp, err := dc().R().
+	resp, err := dcnl().R().
 		SetHeaders(map[string]string{hdrContentTypeKey: "application/xml", hdrAcceptKey: "application/xml"}).
 		SetBody(`<?xml version="1.0" encoding="UTF-8"?><Request>XML Content sending to server</Request>`).
 		Put(ts.URL + "/xml")
@@ -1223,7 +1223,7 @@ func TestOnBeforeMiddleware(t *testing.T) {
 	ts := createGenericServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.OnBeforeRequest(func(c *Client, r *Request) error {
 		r.SetHeader("X-Custom-Request-Middleware", "OnBeforeRequest middleware")
 		return nil
@@ -1247,7 +1247,7 @@ func TestHTTPAutoRedirectUpTo10(t *testing.T) {
 	ts := createRedirectServer(t)
 	defer ts.Close()
 
-	_, err := dc().R().Get(ts.URL + "/redirect-1")
+	_, err := dcnl().R().Get(ts.URL + "/redirect-1")
 
 	assertEqual(t, true, (err.Error() == "Get /redirect-11: stopped after 10 redirects" ||
 		err.Error() == "Get \"/redirect-11\": stopped after 10 redirects"))
@@ -1257,7 +1257,7 @@ func TestHostCheckRedirectPolicy(t *testing.T) {
 	ts := createRedirectServer(t)
 	defer ts.Close()
 
-	c := dc().
+	c := dcnl().
 		SetRedirectPolicy(DomainCheckRedirectPolicy("127.0.0.1"))
 
 	_, err := c.R().Get(ts.URL + "/redirect-host-check-1")
@@ -1271,14 +1271,14 @@ func TestHttpMethods(t *testing.T) {
 	defer ts.Close()
 
 	t.Run("head method", func(t *testing.T) {
-		resp, err := dclr().Head(ts.URL + "/")
+		resp, err := dcnldr().Head(ts.URL + "/")
 
 		assertError(t, err)
 		assertEqual(t, http.StatusOK, resp.StatusCode())
 	})
 
 	t.Run("options method", func(t *testing.T) {
-		resp, err := dclr().Options(ts.URL + "/options")
+		resp, err := dcnldr().Options(ts.URL + "/options")
 
 		assertError(t, err)
 		assertEqual(t, http.StatusOK, resp.StatusCode())
@@ -1286,7 +1286,7 @@ func TestHttpMethods(t *testing.T) {
 	})
 
 	t.Run("patch method", func(t *testing.T) {
-		resp, err := dclr().Patch(ts.URL + "/patch")
+		resp, err := dcnldr().Patch(ts.URL + "/patch")
 
 		assertError(t, err)
 		assertEqual(t, http.StatusOK, resp.StatusCode())
@@ -1295,7 +1295,7 @@ func TestHttpMethods(t *testing.T) {
 	})
 
 	t.Run("trace method", func(t *testing.T) {
-		resp, err := dclr().Trace(ts.URL + "/trace")
+		resp, err := dcnldr().Trace(ts.URL + "/trace")
 
 		assertError(t, err)
 		assertEqual(t, http.StatusOK, resp.StatusCode())
@@ -1304,7 +1304,7 @@ func TestHttpMethods(t *testing.T) {
 	})
 
 	t.Run("connect method", func(t *testing.T) {
-		resp, err := dclr().Connect(ts.URL + "/connect")
+		resp, err := dcnldr().Connect(ts.URL + "/connect")
 
 		assertError(t, err)
 		assertEqual(t, http.StatusOK, resp.StatusCode())
@@ -1317,9 +1317,21 @@ func TestSendMethod(t *testing.T) {
 	ts := createGenericServer(t)
 	defer ts.Close()
 
+	t.Run("send-get-implicit", func(t *testing.T) {
+		req := dcnldr()
+		req.URL = ts.URL + "/gzip-test"
+
+		resp, err := req.Send()
+
+		assertError(t, err)
+		assertEqual(t, http.StatusOK, resp.StatusCode())
+
+		assertEqual(t, "This is Gzip response testing", resp.String())
+	})
+
 	t.Run("send-get", func(t *testing.T) {
-		req := dclr()
-		req.Method = http.MethodGet
+		req := dcnldr()
+		req.SetMethod(MethodGet)
 		req.URL = ts.URL + "/gzip-test"
 
 		resp, err := req.Send()
@@ -1331,8 +1343,8 @@ func TestSendMethod(t *testing.T) {
 	})
 
 	t.Run("send-options", func(t *testing.T) {
-		req := dclr()
-		req.Method = http.MethodOptions
+		req := dcnldr()
+		req.SetMethod(MethodOptions)
 		req.URL = ts.URL + "/options"
 
 		resp, err := req.Send()
@@ -1345,8 +1357,8 @@ func TestSendMethod(t *testing.T) {
 	})
 
 	t.Run("send-patch", func(t *testing.T) {
-		req := dclr()
-		req.Method = http.MethodPatch
+		req := dcnldr()
+		req.SetMethod(MethodPatch)
 		req.URL = ts.URL + "/patch"
 
 		resp, err := req.Send()
@@ -1358,8 +1370,8 @@ func TestSendMethod(t *testing.T) {
 	})
 
 	t.Run("send-put", func(t *testing.T) {
-		req := dclr()
-		req.Method = http.MethodPut
+		req := dcnldr()
+		req.SetMethod(MethodPut)
 		req.URL = ts.URL + "/plaintext"
 
 		resp, err := req.Send()
@@ -1378,7 +1390,7 @@ func TestRawFileUploadByBody(t *testing.T) {
 	fileBytes, err := os.ReadFile(filepath.Join(getTestDataPath(), "test-img.png"))
 	assertNil(t, err)
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetBody(fileBytes).
 		SetContentLength(true).
 		SetAuthToken("004DDB79-6801-4587-B976-F093E6AC44FF").
@@ -1390,7 +1402,7 @@ func TestRawFileUploadByBody(t *testing.T) {
 }
 
 func TestProxySetting(t *testing.T) {
-	c := dc()
+	c := dcnl()
 
 	transport, err := c.Transport()
 
@@ -1426,7 +1438,7 @@ func TestGetClient(t *testing.T) {
 }
 
 func TestIncorrectURL(t *testing.T) {
-	c := dc()
+	c := dcnl()
 	_, err := c.R().Get("//not.a.user@%66%6f%6f.com/just/a/path/also")
 	assertEqual(t, true, (strings.Contains(err.Error(), "parse //not.a.user@%66%6f%6f.com/just/a/path/also") ||
 		strings.Contains(err.Error(), "parse \"//not.a.user@%66%6f%6f.com/just/a/path/also\"")))
@@ -1443,7 +1455,7 @@ func TestDetectContentTypeForPointer(t *testing.T) {
 
 	user := &User{Username: "testuser", Password: "testpass"}
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetBody(user).
 		SetResult(AuthSuccess{}).
 		Post(ts.URL + "/login")
@@ -1472,7 +1484,7 @@ func TestDetectContentTypeForPointerWithSlice(t *testing.T) {
 		{FirstName: "firstname3", LastName: "lastname3", ZipCode: "10003"},
 	}
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetBody(users).
 		Post(ts.URL + "/users")
 
@@ -1497,7 +1509,7 @@ func TestDetectContentTypeForPointerWithSliceMap(t *testing.T) {
 	var users []map[string]any
 	users = append(users, usersmap)
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetBody(&users).
 		Post(ts.URL + "/usersmap")
 
@@ -1519,7 +1531,7 @@ func TestDetectContentTypeForSlice(t *testing.T) {
 		{FirstName: "firstname3", LastName: "lastname3", ZipCode: "10003"},
 	}
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetBody(users).
 		Post(ts.URL + "/users")
 
@@ -1535,7 +1547,7 @@ func TestMultiParamsQueryString(t *testing.T) {
 	ts1 := createGetServer(t)
 	defer ts1.Close()
 
-	client := dc()
+	client := dcnl()
 	req1 := client.R()
 
 	client.SetQueryParam("status", "open")
@@ -1577,7 +1589,7 @@ func TestSetQueryStringTypical(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetQueryString("productId=232&template=fresh-sample&cat=resty&source=google&kw=buy a lot more").
 		Get(ts.URL)
 
@@ -1586,7 +1598,7 @@ func TestSetQueryStringTypical(t *testing.T) {
 	assertEqual(t, "200 OK", resp.Status())
 	assertEqual(t, "TestGet: text response", resp.String())
 
-	resp, err = dclr().
+	resp, err = dcnldr().
 		SetQueryString("&%%amp;").
 		Get(ts.URL)
 
@@ -1600,7 +1612,7 @@ func TestSetHeaderVerbatim(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	r := dclr().
+	r := dcnldr().
 		SetHeaderVerbatim("header-lowercase", "value_lowercase").
 		SetHeader("header-lowercase", "value_standard")
 
@@ -1613,7 +1625,7 @@ func TestSetHeaderMultipleValue(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	r := dclr().
+	r := dcnldr().
 		SetHeaderMultiValues(map[string][]string{
 			"Content":       {"text/*", "text/html", "*"},
 			"Authorization": {"Bearer xyz"},
@@ -1628,7 +1640,7 @@ func TestOutputFileWithBaseDirAndRelativePath(t *testing.T) {
 	defer cleanupFiles(".testdata/dir-sample")
 
 	baseOutputDir := filepath.Join(getTestDataPath(), "dir-sample")
-	client := dc().
+	client := dcnl().
 		SetRedirectPolicy(FlexibleRedirectPolicy(10)).
 		SetOutputDirectory(baseOutputDir).
 		SetDebug(true)
@@ -1649,7 +1661,7 @@ func TestOutputFileWithBaseDirAndRelativePath(t *testing.T) {
 }
 
 func TestOutputFileWithBaseDirError(t *testing.T) {
-	c := dc().SetRedirectPolicy(FlexibleRedirectPolicy(10)).
+	c := dcnl().SetRedirectPolicy(FlexibleRedirectPolicy(10)).
 		SetOutputDirectory(filepath.Join(getTestDataPath(), `go-resty\0`))
 
 	_ = c
@@ -1660,7 +1672,7 @@ func TestOutputPathDirNotExists(t *testing.T) {
 	defer ts.Close()
 	defer cleanupFiles(filepath.Join(".testdata", "not-exists-dir"))
 
-	client := dc().
+	client := dcnl().
 		SetRedirectPolicy(FlexibleRedirectPolicy(10)).
 		SetOutputDirectory(filepath.Join(getTestDataPath(), "not-exists-dir"))
 
@@ -1678,7 +1690,7 @@ func TestOutputFileAbsPath(t *testing.T) {
 	defer ts.Close()
 	defer cleanupFiles(filepath.Join(".testdata", "go-resty"))
 
-	_, err := dcr().
+	_, err := dcnlr().
 		SetOutputFile(filepath.Join(getTestDataPath(), "go-resty", "test-img-success-2.png")).
 		Get(ts.URL + "/my-image.png")
 
@@ -1689,7 +1701,7 @@ func TestContextInternal(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	r := dc().R().
+	r := dcnl().R().
 		SetQueryParam("request_no", strconv.FormatInt(time.Now().Unix(), 10))
 
 	resp, err := r.Get(ts.URL + "/")
@@ -1699,7 +1711,7 @@ func TestContextInternal(t *testing.T) {
 }
 
 func TestSRV(t *testing.T) {
-	c := dc().
+	c := dcnl().
 		SetRedirectPolicy(FlexibleRedirectPolicy(20)).
 		SetScheme("http")
 
@@ -1718,7 +1730,7 @@ func TestSRV(t *testing.T) {
 }
 
 func TestSRVInvalidService(t *testing.T) {
-	_, err := dc().R().
+	_, err := dcnl().R().
 		SetSRV(&SRVRecord{"nonexistantservice", "sampledomain"}).
 		Get("/")
 
@@ -1730,30 +1742,31 @@ func TestRequestDoNotParseResponse(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	client := dc().SetDoNotParseResponse(true)
-	resp, err := client.R().
-		SetQueryParam("request_no", strconv.FormatInt(time.Now().Unix(), 10)).
-		Get(ts.URL + "/")
-
-	assertError(t, err)
+	t.Run("do not parse response 1", func(t *testing.T) {
+		client := dcnl().SetDoNotParseResponse(true)
+		resp, err := client.R().
+			SetQueryParam("request_no", strconv.FormatInt(time.Now().Unix(), 10)).
+			Get(ts.URL + "/")
 
-	buf := acquireBuffer()
-	defer releaseBuffer(buf)
-	_, _ = io.Copy(buf, resp.Body)
+		assertError(t, err)
 
-	assertEqual(t, "TestGet: text response", buf.String())
-	_ = resp.Body.Close()
+		b, err := io.ReadAll(resp.Body)
+		_ = resp.Body.Close()
+		assertError(t, err)
+		assertEqual(t, "TestGet: text response", string(b))
+	})
 
-	// Manually setting RawResponse as nil
-	resp, err = dc().R().
-		SetDoNotParseResponse(true).
-		Get(ts.URL + "/")
+	t.Run("manual reset raw response - do not parse response 2", func(t *testing.T) {
+		resp, err := dcnl().R().
+			SetDoNotParseResponse(true).
+			Get(ts.URL + "/")
 
-	assertError(t, err)
+		assertError(t, err)
 
-	resp.RawResponse = nil
-	assertEqual(t, 0, resp.StatusCode())
-	assertEqual(t, "", resp.String())
+		resp.RawResponse = nil
+		assertEqual(t, 0, resp.StatusCode())
+		assertEqual(t, "", resp.String())
+	})
 }
 
 func TestRequestDoNotParseResponseDebugLog(t *testing.T) {
@@ -1761,7 +1774,7 @@ func TestRequestDoNotParseResponseDebugLog(t *testing.T) {
 	defer ts.Close()
 
 	t.Run("do not parse response debug log client level", func(t *testing.T) {
-		c := dc().
+		c := dcnl().
 			SetDoNotParseResponse(true).
 			SetDebug(true)
 
@@ -1777,7 +1790,7 @@ func TestRequestDoNotParseResponseDebugLog(t *testing.T) {
 	})
 
 	t.Run("do not parse response debug log request level", func(t *testing.T) {
-		c := dc()
+		c := dcnl()
 
 		var lgr bytes.Buffer
 		c.outputLogTo(&lgr)
@@ -1801,7 +1814,7 @@ func TestRequestExpectContentTypeTest(t *testing.T) {
 	ts := createGenericServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	resp, err := c.R().
 		SetResult(noCtTest{}).
 		SetExpectResponseContentType("application/json").
@@ -1819,7 +1832,7 @@ func TestGetPathParamAndPathParams(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc().
+	c := dcnl().
 		SetBaseURL(ts.URL).
 		SetPathParam("userId", "sample@sample.com")
 
@@ -1840,7 +1853,7 @@ func TestReportMethodSupportsPayload(t *testing.T) {
 	ts := createGenericServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	resp, err := c.R().
 		SetBody("body").
 		Execute("REPORT", ts.URL+"/report")
@@ -1870,7 +1883,7 @@ func TestRequestOverridesClientAuthorizationHeader(t *testing.T) {
 	ts := createAuthServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	c.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}).
 		SetHeader("Authorization", "some token").
 		SetBaseURL(ts.URL + "/")
@@ -1890,7 +1903,7 @@ func TestRequestFileUploadAsReader(t *testing.T) {
 	file, _ := os.Open(filepath.Join(getTestDataPath(), "test-img.png"))
 	defer file.Close()
 
-	resp, err := dclr().
+	resp, err := dcnldr().
 		SetBody(file).
 		SetHeader("Content-Type", "image/png").
 		Post(ts.URL + "/upload")
@@ -1902,7 +1915,7 @@ func TestRequestFileUploadAsReader(t *testing.T) {
 	file, _ = os.Open(filepath.Join(getTestDataPath(), "test-img.png"))
 	defer file.Close()
 
-	resp, err = dclr().
+	resp, err = dcnldr().
 		SetBody(file).
 		SetHeader("Content-Type", "image/png").
 		SetContentLength(true).
@@ -1917,7 +1930,7 @@ func TestHostHeaderOverride(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	resp, err := dc().R().
+	resp, err := dcnl().R().
 		SetHeader("Host", "myhostname").
 		Get(ts.URL + "/host-header")
 
@@ -1939,7 +1952,7 @@ func TestNotFoundWithError(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	resp, err := dc().R().
+	resp, err := dcnl().R().
 		SetHeader(hdrContentTypeKey, "application/json").
 		SetError(&httpError).
 		Get(ts.URL + "/not-found-with-error")
@@ -1959,7 +1972,7 @@ func TestNotFoundWithoutError(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc().outputLogTo(os.Stdout)
+	c := dcnl().outputLogTo(os.Stdout)
 	resp, err := c.R().
 		SetError(&httpError).
 		SetHeader(hdrContentTypeKey, "application/json").
@@ -1978,7 +1991,7 @@ func TestPathParamURLInput(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc().
+	c := dcnl().
 		SetBaseURL(ts.URL).
 		SetPathParams(map[string]string{
 			"userId": "sample@sample.com",
@@ -2004,7 +2017,7 @@ func TestRawPathParamURLInput(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc().SetDebug(true).
+	c := dcnl().
 		SetBaseURL(ts.URL).
 		SetRawPathParams(map[string]string{
 			"userId": "sample@sample.com",
@@ -2014,7 +2027,7 @@ func TestRawPathParamURLInput(t *testing.T) {
 	assertEqual(t, "sample@sample.com", c.RawPathParams()["userId"])
 	assertEqual(t, "users/developers", c.RawPathParams()["path"])
 
-	resp, err := c.R().
+	resp, err := c.R().EnableDebug().
 		SetRawPathParams(map[string]string{
 			"subAccountId": "100002",
 			"website":      "https://example.com",
@@ -2035,7 +2048,7 @@ func TestTraceInfo(t *testing.T) {
 
 	serverAddr := ts.URL[strings.LastIndex(ts.URL, "/")+1:]
 
-	client := dc()
+	client := dcnl()
 	client.SetBaseURL(ts.URL).EnableTrace()
 	for _, u := range []string{"/", "/json", "/long-text", "/long-json"} {
 		resp, err := client.R().Get(u)
@@ -2080,7 +2093,7 @@ func TestTraceInfoWithoutEnableTrace(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	client := dc()
+	client := dcnl()
 	client.SetBaseURL(ts.URL)
 	for _, u := range []string{"/", "/json", "/long-text", "/long-json"} {
 		resp, err := client.R().Get(u)
@@ -2098,7 +2111,7 @@ func TestTraceInfoWithoutEnableTrace(t *testing.T) {
 }
 
 func TestTraceInfoOnTimeout(t *testing.T) {
-	client := dc()
+	client := dcnl()
 	client.SetBaseURL("http://resty-nowhere.local").EnableTrace()
 
 	resp, err := client.R().Get("/")
@@ -2211,7 +2224,7 @@ func TestPostMapTemporaryRedirect(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	resp, err := c.R().SetBody(map[string]string{"username": "testuser", "password": "testpass"}).
 		Post(ts.URL + "/redirect")
 
@@ -2220,6 +2233,19 @@ func TestPostMapTemporaryRedirect(t *testing.T) {
 	assertEqual(t, http.StatusOK, resp.StatusCode())
 }
 
+func TestPostWith204Responset(t *testing.T) {
+	ts := createPostServer(t)
+	defer ts.Close()
+
+	c := dcnl()
+	resp, err := c.R().SetBody(map[string]string{"username": "testuser", "password": "testpass"}).
+		Post(ts.URL + "/204-response")
+
+	assertNil(t, err)
+	assertNotNil(t, resp)
+	assertEqual(t, http.StatusNoContent, resp.StatusCode())
+}
+
 type brokenReadCloser struct{}
 
 func (b brokenReadCloser) Read(p []byte) (n int, err error) {
@@ -2234,11 +2260,11 @@ func TestPostBodyError(t *testing.T) {
 	ts := createPostServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	resp, err := c.R().SetBody(brokenReadCloser{}).Post(ts.URL + "/redirect")
 	assertNotNil(t, err)
-	assertEqual(t, "read error", err.Error())
-	assertNil(t, resp)
+	assertEqual(t, "read error", errors.Unwrap(err).Error())
+	assertNotNil(t, resp)
 }
 
 func TestSetResultMustNotPanicOnNil(t *testing.T) {
@@ -2247,14 +2273,14 @@ func TestSetResultMustNotPanicOnNil(t *testing.T) {
 			t.Errorf("must not panic")
 		}
 	}()
-	dc().R().SetResult(nil)
+	dcnl().R().SetResult(nil)
 }
 
 func TestRequestClone(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc()
+	c := dcnl()
 	parent := c.R()
 
 	// set an non-interface value
@@ -2317,10 +2343,43 @@ func TestRequestClone(t *testing.T) {
 	assertEqual(t, "xmpp-server-clone", clone.SRV.Service)
 }
 
+func TestResponseBodyUnlimitedReads(t *testing.T) {
+	ts := createPostServer(t)
+	defer ts.Close()
+
+	user := &User{Username: "testuser", Password: "testpass"}
+
+	c := dcnl().
+		SetJSONEscapeHTML(false).
+		SetResponseBodyUnlimitedReads(true)
+
+	assertEqual(t, true, c.ResponseBodyUnlimitedReads())
+
+	resp, err := c.R().
+		SetHeader(hdrContentTypeKey, "application/json; charset=utf-8").
+		SetBody(user).
+		SetResult(&AuthSuccess{}).
+		Post(ts.URL + "/login")
+
+	assertError(t, err)
+	assertEqual(t, http.StatusOK, resp.StatusCode())
+	assertEqual(t, int64(50), resp.Size())
+
+	t.Logf("Result Success: %q", resp.Result().(*AuthSuccess))
+
+	for i := 1; i <= 5; i++ {
+		b, err := io.ReadAll(resp.Body)
+		assertNil(t, err)
+		assertEqual(t, `{ "id": "success", "message": "login successful" }`, string(b))
+	}
+
+	logResponse(t, resp)
+}
+
 // This test methods exist for test coverage purpose
 // to validate the getter and setter
 func TestRequestSettingsCoverage(t *testing.T) {
-	c := dc()
+	c := dcnl()
 
 	c.R().SetCloseConnection(true)
 
@@ -2329,4 +2388,8 @@ func TestRequestSettingsCoverage(t *testing.T) {
 	srv := []*net.SRV{}
 	srv = append(srv, &net.SRV{})
 	c.R().selectAddr(srv, "/", 1)
+
+	c.R().SetResponseBodyUnlimitedReads(true)
+
+	c.R().DisableDebug()
 }
diff --git a/resty_test.go b/resty_test.go
index 3d8f62d..30b5477 100644
--- a/resty_test.go
+++ b/resty_test.go
@@ -5,6 +5,7 @@
 package resty
 
 import (
+	"bytes"
 	"compress/gzip"
 	"crypto/md5"
 	"encoding/base64"
@@ -318,6 +319,8 @@ func createPostServer(t *testing.T) *httptest.Server {
 				}
 				http.SetCookie(w, &cookie)
 				w.WriteHeader(http.StatusOK)
+			case "/204-response":
+				w.WriteHeader(http.StatusNoContent)
 			}
 		}
 	})
@@ -817,27 +820,27 @@ func createTestServer(fn func(w http.ResponseWriter, r *http.Request)) *httptest
 	return httptest.NewServer(http.HandlerFunc(fn))
 }
 
-func dc() *Client {
+func dcnl() *Client {
 	c := New().
 		outputLogTo(io.Discard)
 	return c
 }
 
-func dcl() *Client {
+func dcld() (*Client, *bytes.Buffer) {
+	logBuf := acquireBuffer()
 	c := New().
-		SetDebug(true).
-		outputLogTo(io.Discard)
-	return c
+		EnableDebug().
+		outputLogTo(logBuf)
+	return c, logBuf
 }
 
-func dcr() *Request {
-	return dc().R()
+func dcnlr() *Request {
+	return dcnl().R()
 }
 
-func dclr() *Request {
-	c := dc().
-		SetDebug(true).
-		outputLogTo(io.Discard)
+func dcnldr() *Request {
+	c := dcnl().
+		SetDebug(true)
 	return c.R()
 }
 
diff --git a/retry_test.go b/retry_test.go
index 7512777..0868301 100644
--- a/retry_test.go
+++ b/retry_test.go
@@ -143,7 +143,7 @@ func TestConditionalGet(t *testing.T) {
 		return attemptCount != externalCounter
 	})
 
-	client := dc().AddRetryCondition(check).SetRetryCount(1)
+	client := dcnl().AddRetryCondition(check).SetRetryCount(1)
 	resp, err := client.R().
 		SetQueryParam("request_no", strconv.FormatInt(time.Now().Unix(), 10)).
 		Get(ts.URL + "/")
@@ -171,7 +171,7 @@ func TestConditionalGetRequestLevel(t *testing.T) {
 	})
 
 	// Clear the default client.
-	client := dc()
+	client := dcnl()
 	resp, err := client.R().
 		AddRetryCondition(check).
 		SetRetryCount(1).
@@ -195,7 +195,7 @@ func TestClientRetryGet(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc().
+	c := dcnl().
 		SetTimeout(time.Second * 3).
 		SetRetryCount(3)
 
@@ -224,7 +224,7 @@ func TestClientRetryWait(t *testing.T) {
 	retryWaitTime := time.Duration(3) * time.Second
 	retryMaxWaitTime := time.Duration(9) * time.Second
 
-	c := dc().
+	c := dcnl().
 		SetRetryCount(retryCount).
 		SetRetryWaitTime(retryWaitTime).
 		SetRetryMaxWaitTime(retryMaxWaitTime).
@@ -267,7 +267,7 @@ func TestClientRetryWaitMaxInfinite(t *testing.T) {
 	retryWaitTime := time.Duration(3) * time.Second
 	retryMaxWaitTime := time.Duration(-1.0) // negative value
 
-	c := dc().
+	c := dcnl().
 		SetRetryCount(retryCount).
 		SetRetryWaitTime(retryWaitTime).
 		SetRetryMaxWaitTime(retryMaxWaitTime).
@@ -303,7 +303,7 @@ func TestClientRetryWaitMaxMinimum(t *testing.T) {
 
 	const retryMaxWaitTime = time.Nanosecond // minimal duration value
 
-	c := dc().
+	c := dcnl().
 		SetRetryCount(1).
 		SetRetryMaxWaitTime(retryMaxWaitTime).
 		AddRetryCondition(func(*Response, error) bool { return true })
@@ -328,7 +328,7 @@ func TestClientRetryWaitCallbackError(t *testing.T) {
 		return 0, errors.New("quota exceeded")
 	}
 
-	c := dc().
+	c := dcnl().
 		SetRetryCount(retryCount).
 		SetRetryWaitTime(retryWaitTime).
 		SetRetryMaxWaitTime(retryMaxWaitTime).
@@ -368,7 +368,7 @@ func TestClientRetryWaitCallback(t *testing.T) {
 		return 5 * time.Second, nil
 	}
 
-	c := dc().
+	c := dcnl().
 		SetRetryCount(retryCount).
 		SetRetryWaitTime(retryWaitTime).
 		SetRetryMaxWaitTime(retryMaxWaitTime).
@@ -416,7 +416,7 @@ func TestClientRetryWaitCallbackTooShort(t *testing.T) {
 		return 2 * time.Second, nil // too short duration
 	}
 
-	c := dc().
+	c := dcnl().
 		SetRetryCount(retryCount).
 		SetRetryWaitTime(retryWaitTime).
 		SetRetryMaxWaitTime(retryMaxWaitTime).
@@ -464,7 +464,7 @@ func TestClientRetryWaitCallbackTooLong(t *testing.T) {
 		return 4 * time.Second, nil // too long duration
 	}
 
-	c := dc().
+	c := dcnl().
 		SetRetryCount(retryCount).
 		SetRetryWaitTime(retryWaitTime).
 		SetRetryMaxWaitTime(retryMaxWaitTime).
@@ -512,7 +512,7 @@ func TestClientRetryWaitCallbackSwitchToDefault(t *testing.T) {
 		return 0, nil // use default algorithm to determine retry-after time
 	}
 
-	c := dc().
+	c := dcnl().
 		EnableTrace().
 		SetRetryCount(retryCount).
 		SetRetryWaitTime(retryWaitTime).
@@ -564,7 +564,7 @@ func TestClientRetryCancel(t *testing.T) {
 	retryWaitTime := time.Duration(10) * time.Second
 	retryMaxWaitTime := time.Duration(20) * time.Second
 
-	c := dc().
+	c := dcnl().
 		SetRetryCount(retryCount).
 		SetRetryWaitTime(retryWaitTime).
 		SetRetryMaxWaitTime(retryMaxWaitTime).
@@ -606,7 +606,7 @@ func TestClientRetryPost(t *testing.T) {
 	var users []map[string]any
 	users = append(users, usersmap)
 
-	c := dc()
+	c := dcnl()
 	c.SetRetryCount(3)
 	c.AddRetryCondition(RetryConditionFunc(func(r *Response, _ error) bool {
 		return r.StatusCode() >= http.StatusInternalServerError
@@ -637,7 +637,7 @@ func TestClientRetryErrorRecover(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc().
+	c := dcnl().
 		SetRetryCount(2).
 		SetError(AuthError{}).
 		AddRetryCondition(
@@ -670,7 +670,7 @@ func TestClientRetryCount(t *testing.T) {
 
 	attempt := 0
 
-	c := dc().
+	c := dcnl().
 		SetTimeout(time.Second * 3).
 		SetRetryCount(1).
 		AddRetryCondition(
@@ -699,7 +699,7 @@ func TestClientErrorRetry(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()
 
-	c := dc().
+	c := dcnl().
 		SetTimeout(time.Second * 3).
 		SetRetryCount(1).
 		AddRetryAfterErrorCondition()
@@ -730,7 +730,7 @@ func TestClientRetryHook(t *testing.T) {
 		attempt++
 	}
 
-	c := dc().
+	c := dcnl().
 		SetRetryCount(2).
 		SetTimeout(time.Second * 3).
 		AddRetryHook(retryHook)
@@ -786,7 +786,7 @@ func TestResetMultipartReaderSeekStartError(t *testing.T) {
 		bytes.NewReader([]byte("test")),
 	}
 
-	c := dc().
+	c := dcnl().
 		SetRetryCount(2).
 		SetTimeout(time.Second * 3).
 		SetRetryResetReaders(true).
@@ -812,7 +812,7 @@ func TestClientResetMultipartReaders(t *testing.T) {
 	bufReader := bytes.NewReader(buf)
 	bufCpy := make([]byte, len(buf))
 
-	c := dc().
+	c := dcnl().
 		SetRetryCount(2).
 		SetTimeout(time.Second * 3).
 		SetRetryResetReaders(true).
@@ -847,7 +847,7 @@ func TestRequestResetMultipartReaders(t *testing.T) {
 	bufReader := bytes.NewReader(buf)
 	bufCpy := make([]byte, len(buf))
 
-	c := dc().
+	c := dcnl().
 		SetTimeout(time.Second * 3).
 		AddRetryAfterErrorCondition().
 		AddRetryHook(
diff --git a/util_test.go b/util_test.go
index ccf816c..0c24503 100644
--- a/util_test.go
+++ b/util_test.go
@@ -9,6 +9,7 @@ import (
 	"errors"
 	"mime/multipart"
 	"net/url"
+	"strings"
 	"testing"
 )
 
@@ -108,6 +109,8 @@ func TestRestyErrorFuncs(t *testing.T) {
 	ne1 := errors.New("new error 1")
 	nie1 := errors.New("inner error 1")
 
+	assertNil(t, wrapErrors(nil, nil))
+
 	e := wrapErrors(ne1, nie1)
 	assertEqual(t, "new error 1", e.Error())
 	assertEqual(t, "inner error 1", errors.Unwrap(e).Error())
@@ -118,3 +121,20 @@ func TestRestyErrorFuncs(t *testing.T) {
 	e = wrapErrors(nil, nie1)
 	assertEqual(t, "inner error 1", e.Error())
 }
+
+// This test methods exist for test coverage purpose
+// to validate the getter and setter
+func TestUtilMiscTestCoverage(t *testing.T) {
+	l := &limitReadCloser{r: strings.NewReader("hello test close for no io.Closer")}
+	assertNil(t, l.Close())
+
+	r := &readCopier{s: strings.NewReader("hello test close for no io.Closer")}
+	assertNil(t, r.Close())
+
+	v := struct {
+		ID      string `json:"id"`
+		Message string `json:"message"`
+	}{}
+	err := decodeJSON(bytes.NewReader([]byte(`{\"  \": \"some value\"}`)), &v)
+	assertEqual(t, "invalid character '\\\\' looking for beginning of object key string", err.Error())
+}