Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ func (c *Client) SetDebug(d bool) *Client {
return c
}

// SetDebugBodyLimit sets the maximum size for which the response body will be logged in debug mode.
// SetDebugBodyLimit sets the maximum size for which the response and request body will be logged in debug mode.
// client.SetDebugBodyLimit(1000000)
func (c *Client) SetDebugBodyLimit(sl int64) *Client {
c.debugBodySizeLimit = sl
Expand Down
2 changes: 1 addition & 1 deletion middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ func addCredentials(c *Client, r *Request) error {
func requestLogger(c *Client, r *Request) error {
if c.Debug {
rr := r.RawRequest
rl := &RequestLog{Header: copyHeaders(rr.Header), Body: r.fmtBodyString()}
rl := &RequestLog{Header: copyHeaders(rr.Header), Body: r.fmtBodyString(c.debugBodySizeLimit)}
if c.requestLog != nil {
if err := c.requestLog(rl); err != nil {
return err
Expand Down
89 changes: 51 additions & 38 deletions request.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ package resty
import (
"bytes"
"context"
"encoding/base64"
"encoding/json"
"encoding/xml"
"fmt"
Expand Down Expand Up @@ -662,51 +661,65 @@ type SRVRecord struct {
// Request Unexported methods
//_______________________________________________________________________

func (r *Request) fmtBodyString() (body string) {
func (r *Request) fmtBodyString(sl int64) (body string) {
body = "***** NO CONTENT *****"
if isPayloadSupported(r.Method, r.client.AllowGetMethodPayload) {
if _, ok := r.Body.(io.Reader); ok {
body = "***** BODY IS io.Reader *****"
return
}
if !isPayloadSupported(r.Method, r.client.AllowGetMethodPayload) {
return
}

// multipart or form-data
if r.isMultiPart || r.isFormData {
body = r.bodyBuf.String()
return
}
if _, ok := r.Body.(io.Reader); ok {
body = "***** BODY IS io.Reader *****"
return
}

// request body data
if r.Body == nil {
// multipart or form-data
if r.isMultiPart || r.isFormData {
bodySize := int64(r.bodyBuf.Len())
if bodySize > sl {
body = fmt.Sprintf("***** REQUEST TOO LARGE (size - %d) *****", bodySize)
return
}
var prtBodyBytes []byte
var err error

contentType := r.Header.Get(hdrContentTypeKey)
kind := kindOf(r.Body)
if canJSONMarshal(contentType, kind) {
prtBodyBytes, err = json.MarshalIndent(&r.Body, "", " ")
} else if IsXMLType(contentType) && (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 {
body = b
return
body = r.bodyBuf.String()
return
}

// request body data
if r.Body == nil {
return
}
var prtBodyBytes []byte
var err error

contentType := r.Header.Get(hdrContentTypeKey)
kind := kindOf(r.Body)
if canJSONMarshal(contentType, kind) {
prtBodyBytes, err = json.MarshalIndent(&r.Body, "", " ")
} else if IsXMLType(contentType) && (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 if b, ok := r.Body.([]byte); ok {
body = base64.StdEncoding.EncodeToString(b)
} else {
body = b
}
} else if b, ok := r.Body.([]byte); ok {
body = fmt.Sprintf("***** BODY IS byte(s) (size - %d) *****", len(b))
return
}

if prtBodyBytes != nil && err == nil {
body = string(prtBodyBytes)
}

if prtBodyBytes != nil && err == nil {
body = string(prtBodyBytes)
if len(body) > 0 {
bodySize := int64(len([]byte(body)))
if bodySize > sl {
body = fmt.Sprintf("***** REQUEST TOO LARGE (size - %d) *****", bodySize)
}
}

Expand Down
79 changes: 79 additions & 0 deletions request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1576,3 +1576,82 @@ func TestTraceInfoWithoutEnableTrace(t *testing.T) {
assertEqual(t, true, tr.TotalTime == 0)
}
}

func TestDebugLoggerRequestBodyTooLarge(t *testing.T) {
ts := createFilePostServer(t)
defer ts.Close()

debugBodySizeLimit := int64(512)

// 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")).
SetHeader("Content-Type", "image/png").
Post(ts.URL + "/upload")
assertNil(t, err)
assertNotNil(t, resp)
assertEqual(t, true, strings.Contains(output.String(), "REQUEST TOO LARGE"))

// upload a text file with no more than 512 bytes
output = bytes.NewBufferString("")
resp, err = New().SetDebug(true).outputLogTo(output).SetDebugBodyLimit(debugBodySizeLimit).R().
SetFile("file", filepath.Join(getTestDataPath(), "text-file.txt")).
SetHeader("Content-Type", "text/plain").
Post(ts.URL + "/upload")
assertNil(t, err)
assertNotNil(t, resp)
assertEqual(t, true, strings.Contains(output.String(), " THIS IS TEXT FILE FOR MULTIPART UPLOAD TEST "))

formTs := createFormPostServer(t)
defer formTs.Close()

// 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{
"first_name": "Alex",
"last_name": strings.Repeat("C", int(debugBodySizeLimit)),
"zip_code": "00001"}).
SetBasicAuth("myuser", "mypass").
Post(formTs.URL + "/profile")
assertNil(t, err)
assertNotNil(t, resp)
assertEqual(t, true, strings.Contains(output.String(), "REQUEST TOO LARGE"))

// post form with no more than 512 bytes data
output = bytes.NewBufferString("")
resp, err = New().SetDebug(true).outputLogTo(output).SetDebugBodyLimit(debugBodySizeLimit).R().
SetFormData(map[string]string{
"first_name": "Alex",
"last_name": "C",
"zip_code": "00001"}).
SetBasicAuth("myuser", "mypass").
Post(formTs.URL + "/profile")
assertNil(t, err)
assertNotNil(t, resp)
assertEqual(t, true, strings.Contains(output.String(), "Alex"))

// post string with more than 512 bytes data
output = bytes.NewBufferString("")
resp, err = New().SetDebug(true).outputLogTo(output).SetDebugBodyLimit(debugBodySizeLimit).R().
SetBody(`{
"first_name": "Alex",
"last_name": "` + strings.Repeat("C", int(debugBodySizeLimit)) + `C",
"zip_code": "00001"}`).
SetBasicAuth("myuser", "mypass").
Post(formTs.URL + "/profile")
assertNil(t, err)
assertNotNil(t, resp)
assertEqual(t, true, strings.Contains(output.String(), "REQUEST TOO LARGE"))

// post slice with more than 512 bytes data
output = bytes.NewBufferString("")
resp, err = New().SetDebug(true).outputLogTo(output).SetDebugBodyLimit(debugBodySizeLimit).R().
SetBody([]string{strings.Repeat("C", int(debugBodySizeLimit))}).
SetBasicAuth("myuser", "mypass").
Post(formTs.URL + "/profile")
assertNil(t, err)
assertNotNil(t, resp)
assertEqual(t, true, strings.Contains(output.String(), "REQUEST TOO LARGE"))
}