API handler opts modifier (#26148)
* POC for API handler opts modifier * Made upload POSt api a file upload API * Specified file upload local API * Specified file upload local API * Specified file upload API * Simplified handler params * Added basic security checks * Fixed i18n * used type for API handler options * Removed limited reader from util deserializers (#26263)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
ecb09de6c7
Коммит
521844fed5
@@ -498,10 +498,9 @@ func ArrayFromJSON(data io.Reader) []string {
|
||||
return objmap
|
||||
}
|
||||
|
||||
func SortedArrayFromJSON(data io.Reader, maxBytes int64) ([]string, error) {
|
||||
func SortedArrayFromJSON(data io.Reader) ([]string, error) {
|
||||
var obj []string
|
||||
lr := io.LimitReader(data, maxBytes)
|
||||
err := json.NewDecoder(lr).Decode(&obj)
|
||||
err := json.NewDecoder(data).Decode(&obj)
|
||||
if err != nil || obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -510,10 +509,9 @@ func SortedArrayFromJSON(data io.Reader, maxBytes int64) ([]string, error) {
|
||||
return RemoveDuplicateStrings(obj), nil
|
||||
}
|
||||
|
||||
func NonSortedArrayFromJSON(data io.Reader, maxBytes int64) ([]string, error) {
|
||||
func NonSortedArrayFromJSON(data io.Reader) ([]string, error) {
|
||||
var obj []string
|
||||
lr := io.LimitReader(data, maxBytes)
|
||||
err := json.NewDecoder(lr).Decode(&obj)
|
||||
err := json.NewDecoder(data).Decode(&obj)
|
||||
if err != nil || obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -555,9 +553,8 @@ func StringInterfaceFromJSON(data io.Reader) map[string]any {
|
||||
return objmap
|
||||
}
|
||||
|
||||
func StructFromJSONLimited[V any](data io.Reader, maxBytes int64, obj *V) error {
|
||||
lr := io.LimitReader(data, maxBytes)
|
||||
err := json.NewDecoder(lr).Decode(&obj)
|
||||
func StructFromJSONLimited[V any](data io.Reader, obj *V) error {
|
||||
err := json.NewDecoder(data).Decode(&obj)
|
||||
if err != nil || obj == nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
@@ -222,7 +221,7 @@ func TestSortedArrayFromJSON(t *testing.T) {
|
||||
t.Run("Successful parse", func(t *testing.T) {
|
||||
ids := []string{NewId(), NewId(), NewId()}
|
||||
b, _ := json.Marshal(ids)
|
||||
a, err := SortedArrayFromJSON(bytes.NewReader(b), 1000)
|
||||
a, err := SortedArrayFromJSON(bytes.NewReader(b))
|
||||
require.NoError(t, err)
|
||||
require.ElementsMatch(t, ids, a)
|
||||
})
|
||||
@@ -230,22 +229,11 @@ func TestSortedArrayFromJSON(t *testing.T) {
|
||||
t.Run("Empty Array", func(t *testing.T) {
|
||||
ids := []string{}
|
||||
b, _ := json.Marshal(ids)
|
||||
a, err := SortedArrayFromJSON(bytes.NewReader(b), 1000)
|
||||
a, err := SortedArrayFromJSON(bytes.NewReader(b))
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, a)
|
||||
})
|
||||
|
||||
t.Run("Error too large", func(t *testing.T) {
|
||||
var ids []string
|
||||
for i := 0; i <= 100; i++ {
|
||||
ids = append(ids, NewId())
|
||||
}
|
||||
b, _ := json.Marshal(ids)
|
||||
_, err := SortedArrayFromJSON(bytes.NewReader(b), 1000)
|
||||
require.Error(t, err)
|
||||
require.ErrorIs(t, err, io.ErrUnexpectedEOF)
|
||||
})
|
||||
|
||||
t.Run("Duplicate keys, returns one", func(t *testing.T) {
|
||||
var ids []string
|
||||
id := NewId()
|
||||
@@ -253,7 +241,7 @@ func TestSortedArrayFromJSON(t *testing.T) {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
b, _ := json.Marshal(ids)
|
||||
a, err := SortedArrayFromJSON(bytes.NewReader(b), 26000)
|
||||
a, err := SortedArrayFromJSON(bytes.NewReader(b))
|
||||
require.NoError(t, err)
|
||||
require.Len(t, a, 1)
|
||||
})
|
||||
@@ -263,7 +251,7 @@ func TestNonSortedArrayFromJSON(t *testing.T) {
|
||||
t.Run("Successful parse", func(t *testing.T) {
|
||||
ids := []string{NewId(), NewId(), NewId()}
|
||||
b, _ := json.Marshal(ids)
|
||||
a, err := NonSortedArrayFromJSON(bytes.NewReader(b), 1000)
|
||||
a, err := NonSortedArrayFromJSON(bytes.NewReader(b))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, ids, a)
|
||||
})
|
||||
@@ -271,22 +259,11 @@ func TestNonSortedArrayFromJSON(t *testing.T) {
|
||||
t.Run("Empty Array", func(t *testing.T) {
|
||||
ids := []string{}
|
||||
b, _ := json.Marshal(ids)
|
||||
a, err := NonSortedArrayFromJSON(bytes.NewReader(b), 1000)
|
||||
a, err := NonSortedArrayFromJSON(bytes.NewReader(b))
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, a)
|
||||
})
|
||||
|
||||
t.Run("Error too large", func(t *testing.T) {
|
||||
var ids []string
|
||||
for i := 0; i <= 100; i++ {
|
||||
ids = append(ids, NewId())
|
||||
}
|
||||
b, _ := json.Marshal(ids)
|
||||
_, err := NonSortedArrayFromJSON(bytes.NewReader(b), 1000)
|
||||
require.Error(t, err)
|
||||
require.ErrorIs(t, err, io.ErrUnexpectedEOF)
|
||||
})
|
||||
|
||||
t.Run("Duplicate keys, returns one", func(t *testing.T) {
|
||||
var ids []string
|
||||
id := NewId()
|
||||
@@ -294,7 +271,7 @@ func TestNonSortedArrayFromJSON(t *testing.T) {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
b, _ := json.Marshal(ids)
|
||||
a, err := NonSortedArrayFromJSON(bytes.NewReader(b), 26000)
|
||||
a, err := NonSortedArrayFromJSON(bytes.NewReader(b))
|
||||
require.NoError(t, err)
|
||||
require.Len(t, a, 1)
|
||||
})
|
||||
@@ -1243,7 +1220,7 @@ func TestStructFromJSONLimited(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
b := &TestStruct{}
|
||||
err = StructFromJSONLimited(bytes.NewReader(testStructBytes), 1000, b)
|
||||
err = StructFromJSONLimited(bytes.NewReader(testStructBytes), b)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, b.StringField, "string")
|
||||
@@ -1252,29 +1229,6 @@ func TestStructFromJSONLimited(t *testing.T) {
|
||||
require.Equal(t, b.BoolField, true)
|
||||
})
|
||||
|
||||
t.Run("error too big", func(t *testing.T) {
|
||||
type TestStruct struct {
|
||||
StringField string
|
||||
IntField int
|
||||
FloatField float32
|
||||
BoolField bool
|
||||
}
|
||||
|
||||
testStruct := TestStruct{
|
||||
StringField: "string",
|
||||
IntField: 2,
|
||||
FloatField: 3.1415,
|
||||
BoolField: true,
|
||||
}
|
||||
testStructBytes, err := json.Marshal(testStruct)
|
||||
require.NoError(t, err)
|
||||
|
||||
b := &TestStruct{}
|
||||
err = StructFromJSONLimited(bytes.NewReader(testStructBytes), 10, b)
|
||||
require.Error(t, err)
|
||||
require.ErrorIs(t, err, io.ErrUnexpectedEOF)
|
||||
})
|
||||
|
||||
t.Run("successfully parses nested struct", func(t *testing.T) {
|
||||
type TestStruct struct {
|
||||
StringField string
|
||||
@@ -1313,7 +1267,7 @@ func TestStructFromJSONLimited(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
b := &NestedStruct{}
|
||||
err = StructFromJSONLimited(bytes.NewReader(nestedStructBytes), 1000, b)
|
||||
err = StructFromJSONLimited(bytes.NewReader(nestedStructBytes), b)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, b.FieldA.StringField, "string A")
|
||||
@@ -1329,49 +1283,6 @@ func TestStructFromJSONLimited(t *testing.T) {
|
||||
require.Equal(t, b.FieldC, []int{5, 9, 1, 5, 7})
|
||||
})
|
||||
|
||||
t.Run("errors on too big nested struct", func(t *testing.T) {
|
||||
type TestStruct struct {
|
||||
StringField string
|
||||
IntField int
|
||||
FloatField float32
|
||||
BoolField bool
|
||||
}
|
||||
|
||||
type NestedStruct struct {
|
||||
FieldA TestStruct
|
||||
FieldB TestStruct
|
||||
FieldC []int
|
||||
}
|
||||
|
||||
testStructA := TestStruct{
|
||||
StringField: "string A",
|
||||
IntField: 2,
|
||||
FloatField: 3.1415,
|
||||
BoolField: true,
|
||||
}
|
||||
|
||||
testStructB := TestStruct{
|
||||
StringField: "string B",
|
||||
IntField: 3,
|
||||
FloatField: 100,
|
||||
BoolField: false,
|
||||
}
|
||||
|
||||
nestedStruct := NestedStruct{
|
||||
FieldA: testStructA,
|
||||
FieldB: testStructB,
|
||||
FieldC: []int{5, 9, 1, 5, 7},
|
||||
}
|
||||
|
||||
nestedStructBytes, err := json.Marshal(nestedStruct)
|
||||
require.NoError(t, err)
|
||||
|
||||
b := &NestedStruct{}
|
||||
err = StructFromJSONLimited(bytes.NewReader(nestedStructBytes), 50, b)
|
||||
require.Error(t, err)
|
||||
require.ErrorIs(t, err, io.ErrUnexpectedEOF)
|
||||
})
|
||||
|
||||
t.Run("handles empty structs", func(t *testing.T) {
|
||||
type TestStruct struct{}
|
||||
|
||||
@@ -1380,7 +1291,7 @@ func TestStructFromJSONLimited(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
b := &TestStruct{}
|
||||
err = StructFromJSONLimited(bytes.NewReader(testStructBytes), 1000, b)
|
||||
err = StructFromJSONLimited(bytes.NewReader(testStructBytes), b)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user