mirror of
https://github.com/retailcrm/mg-transport-core.git
synced 2024-11-21 20:56:04 +03:00
fix for body field writer exhaustion
This commit is contained in:
parent
78fadaa520
commit
9c73cabd21
@ -96,6 +96,11 @@ func Body(val any) zap.Field {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return zap.String(BodyAttr, fmt.Sprintf("%#v", val))
|
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{}
|
var m interface{}
|
||||||
if err := json.Unmarshal(data, &m); err == nil {
|
if err := json.Unmarshal(data, &m); err == nil {
|
||||||
return zap.Any(BodyAttr, m)
|
return zap.Any(BodyAttr, m)
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"go.uber.org/zap"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
@ -62,94 +64,133 @@ func TestHTTPStatusName(t *testing.T) {
|
|||||||
|
|
||||||
func TestStreamID(t *testing.T) {
|
func TestStreamID(t *testing.T) {
|
||||||
var cases = []struct {
|
var cases = []struct {
|
||||||
|
name string
|
||||||
input interface{}
|
input interface{}
|
||||||
result interface{}
|
result interface{}
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
name: "empty",
|
||||||
input: "",
|
input: "",
|
||||||
result: "",
|
result: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "string",
|
||||||
input: "test body",
|
input: "test body",
|
||||||
result: "test body",
|
result: "test body",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
val := StreamID(c.input)
|
t.Run(c.name, func(t *testing.T) {
|
||||||
assert.Equal(t, StreamIDAttr, val.Key)
|
val := StreamID(c.input)
|
||||||
assert.Equal(t, c.result, val.String)
|
assert.Equal(t, StreamIDAttr, val.Key)
|
||||||
|
assert.Equal(t, c.result, val.String)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBody(t *testing.T) {
|
func TestBody(t *testing.T) {
|
||||||
var cases = []struct {
|
var cases = []struct {
|
||||||
input interface{}
|
name string
|
||||||
result interface{}
|
input interface{}
|
||||||
|
result interface{}
|
||||||
|
asserts func(t *testing.T, field zap.Field, input, result interface{})
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
name: "empty string input",
|
||||||
input: "",
|
input: "",
|
||||||
result: nil,
|
result: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "nil input",
|
||||||
input: nil,
|
input: nil,
|
||||||
result: nil,
|
result: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "string input",
|
||||||
input: "test body",
|
input: "test body",
|
||||||
result: "test body",
|
result: "test body",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "json input",
|
||||||
input: `{"success":true}`,
|
input: `{"success":true}`,
|
||||||
result: map[string]interface{}{"success": true},
|
result: map[string]interface{}{"success": true},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "empty byte slice input",
|
||||||
input: []byte{},
|
input: []byte{},
|
||||||
result: nil,
|
result: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: nil,
|
name: "byte slice input",
|
||||||
result: nil,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: []byte("test body"),
|
input: []byte("test body"),
|
||||||
result: "test body",
|
result: "test body",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "json byte slice input",
|
||||||
input: []byte(`{"success":true}`),
|
input: []byte(`{"success":true}`),
|
||||||
result: map[string]interface{}{"success": true},
|
result: map[string]interface{}{"success": true},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "eof reader input",
|
||||||
input: newReaderMock(func(p []byte) (n int, err error) {
|
input: newReaderMock(func(p []byte) (n int, err error) {
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}),
|
}),
|
||||||
result: nil,
|
result: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "empty reader input",
|
||||||
input: newReaderMockData([]byte{}),
|
input: newReaderMockData([]byte{}),
|
||||||
result: nil,
|
result: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: "data reader input",
|
||||||
input: newReaderMockData([]byte("ooga booga")),
|
input: newReaderMockData([]byte("ooga booga")),
|
||||||
result: "ooga booga",
|
result: "ooga booga",
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
name: "json data reader input",
|
||||||
input: newReaderMockData([]byte(`{"success":true}`)),
|
input: newReaderMockData([]byte(`{"success":true}`)),
|
||||||
result: map[string]interface{}{"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 {
|
for _, c := range cases {
|
||||||
val := Body(c.input)
|
t.Run(c.name, func(t *testing.T) {
|
||||||
assert.Equal(t, BodyAttr, val.Key)
|
val := Body(c.input)
|
||||||
|
assert.Equal(t, BodyAttr, val.Key)
|
||||||
|
|
||||||
switch assertion := c.result.(type) {
|
switch assertion := c.result.(type) {
|
||||||
case string:
|
case string:
|
||||||
assert.Equal(t, assertion, val.String)
|
assert.Equal(t, assertion, val.String)
|
||||||
case int:
|
case int:
|
||||||
assert.Equal(t, assertion, int(val.Integer))
|
assert.Equal(t, assertion, int(val.Integer))
|
||||||
default:
|
default:
|
||||||
assert.Equal(t, c.result, val.Interface)
|
assert.Equal(t, c.result, val.Interface)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.asserts != nil {
|
||||||
|
c.asserts(t, val, c.input, c.result)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user