Skip to content

Commit

Permalink
Merge pull request #80 from Neur0toxine/fix-body-field
Browse files Browse the repository at this point in the history
fix for body field writer exhaustion
  • Loading branch information
Neur0toxine authored Sep 26, 2024
2 parents 78fadaa + 9c73cab commit ac8765e
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 20 deletions.
5 changes: 5 additions & 0 deletions core/logger/attrs.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ func Body(val any) zap.Field {
if err != nil {
return zap.String(BodyAttr, fmt.Sprintf("%#v", val))
}
if seeker, ok := item.(io.Seeker); ok {
_, _ = seeker.Seek(0, 0)
} else if writer, ok := item.(io.Writer); ok {
_, _ = writer.Write(data)
}
var m interface{}
if err := json.Unmarshal(data, &m); err == nil {
return zap.Any(BodyAttr, m)
Expand Down
81 changes: 61 additions & 20 deletions core/logger/attrs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"bytes"
"errors"
"fmt"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"io"
"net/http"
"testing"
Expand Down Expand Up @@ -62,94 +64,133 @@ func TestHTTPStatusName(t *testing.T) {

func TestStreamID(t *testing.T) {
var cases = []struct {
name string
input interface{}
result interface{}
}{
{
name: "empty",
input: "",
result: "",
},
{
name: "string",
input: "test body",
result: "test body",
},
}
for _, c := range cases {
val := StreamID(c.input)
assert.Equal(t, StreamIDAttr, val.Key)
assert.Equal(t, c.result, val.String)
t.Run(c.name, func(t *testing.T) {
val := StreamID(c.input)
assert.Equal(t, StreamIDAttr, val.Key)
assert.Equal(t, c.result, val.String)
})
}
}

func TestBody(t *testing.T) {
var cases = []struct {
input interface{}
result interface{}
name string
input interface{}
result interface{}
asserts func(t *testing.T, field zap.Field, input, result interface{})
}{
{
name: "empty string input",
input: "",
result: nil,
},
{
name: "nil input",
input: nil,
result: nil,
},
{
name: "string input",
input: "test body",
result: "test body",
},
{
name: "json input",
input: `{"success":true}`,
result: map[string]interface{}{"success": true},
},
{
name: "empty byte slice input",
input: []byte{},
result: nil,
},
{
input: nil,
result: nil,
},
{
name: "byte slice input",
input: []byte("test body"),
result: "test body",
},
{
name: "json byte slice input",
input: []byte(`{"success":true}`),
result: map[string]interface{}{"success": true},
},
{
name: "eof reader input",
input: newReaderMock(func(p []byte) (n int, err error) {
return 0, io.EOF
}),
result: nil,
},
{
name: "empty reader input",
input: newReaderMockData([]byte{}),
result: nil,
},
{
name: "data reader input",
input: newReaderMockData([]byte("ooga booga")),
result: "ooga booga",
},

{
name: "json data reader input",
input: newReaderMockData([]byte(`{"success":true}`)),
result: map[string]interface{}{"success": true},
},
{
name: "check that seeker is rewound",
input: bytes.NewReader([]byte(`{"success":true}`)),
result: map[string]interface{}{"success": true},
asserts: func(t *testing.T, val zap.Field, input, result interface{}) {
data, err := io.ReadAll(input.(io.Reader))
require.NoError(t, err)
assert.Equal(t, []byte(`{"success":true}`), data)
},
},
{
name: "check that writer is rebuilt",
input: bytes.NewBuffer([]byte(`{"success":true}`)),
result: map[string]interface{}{"success": true},
asserts: func(t *testing.T, val zap.Field, input, result interface{}) {
data, err := io.ReadAll(input.(io.Reader))
require.NoError(t, err)
assert.Equal(t, []byte(`{"success":true}`), data)
},
},
}
for _, c := range cases {
val := Body(c.input)
assert.Equal(t, BodyAttr, val.Key)
t.Run(c.name, func(t *testing.T) {
val := Body(c.input)
assert.Equal(t, BodyAttr, val.Key)

switch assertion := c.result.(type) {
case string:
assert.Equal(t, assertion, val.String)
case int:
assert.Equal(t, assertion, int(val.Integer))
default:
assert.Equal(t, c.result, val.Interface)
}

switch assertion := c.result.(type) {
case string:
assert.Equal(t, assertion, val.String)
case int:
assert.Equal(t, assertion, int(val.Integer))
default:
assert.Equal(t, c.result, val.Interface)
}
if c.asserts != nil {
c.asserts(t, val, c.input, c.result)
}
})
}
}

Expand Down

0 comments on commit ac8765e

Please sign in to comment.