[#3176] skip fields query param transformations for non 20x responses

This commit is contained in:
Gani Georgiev 2023-08-23 16:47:02 +03:00
parent 04826ba588
commit bc0222dcb4
3 changed files with 60 additions and 18 deletions

View File

@ -57,6 +57,8 @@
- Fill the `LastVerificationSentAt` and `LastResetSentAt` fields only after a successfull email send ([#3121](https://github.com/pocketbase/pocketbase/issues/3121)). - Fill the `LastVerificationSentAt` and `LastResetSentAt` fields only after a successfull email send ([#3121](https://github.com/pocketbase/pocketbase/issues/3121)).
- Skip API `fields` json transformations for non 20x responses ([#3176](https://github.com/pocketbase/pocketbase/issues/3176)).
- (@todo docs) Added new "Strip urls domain" `editor` field option to allow controlling the default TinyMCE imported urls behavior (_default to `false` for new content_). - (@todo docs) Added new "Strip urls domain" `editor` field option to allow controlling the default TinyMCE imported urls behavior (_default to `false` for new content_).
- Reduced the default JSVM prewarmed pool size to 25 to reduce the initial memory consumptions (_you can manually adjust the pool size with `--hooksPool=50` if you need to, but the default should suffice for most cases_). - Reduced the default JSVM prewarmed pool size to 25 to reduce the initial memory consumptions (_you can manually adjust the pool size with `--hooksPool=50` if you need to, but the default should suffice for most cases_).

View File

@ -25,8 +25,10 @@ func (s *Serializer) Serialize(c echo.Context, i any, indent string) error {
fieldsParam = "fields" fieldsParam = "fields"
} }
statusCode := c.Response().Status
param := c.QueryParam(fieldsParam) param := c.QueryParam(fieldsParam)
if param == "" { if param == "" || statusCode < 200 || statusCode > 299 {
return s.DefaultJSONSerializer.Serialize(c, i, indent) return s.DefaultJSONSerializer.Serialize(c, i, indent)
} }

View File

@ -16,6 +16,7 @@ func TestSerialize(t *testing.T) {
scenarios := []struct { scenarios := []struct {
name string name string
serializer rest.Serializer serializer rest.Serializer
statusCode int
data any data any
query string query string
expected string expected string
@ -23,6 +24,7 @@ func TestSerialize(t *testing.T) {
{ {
"empty query", "empty query",
rest.Serializer{}, rest.Serializer{},
200,
map[string]any{"a": 1, "b": 2, "c": "test"}, map[string]any{"a": 1, "b": 2, "c": "test"},
"", "",
`{"a":1,"b":2,"c":"test"}`, `{"a":1,"b":2,"c":"test"}`,
@ -30,6 +32,7 @@ func TestSerialize(t *testing.T) {
{ {
"empty fields", "empty fields",
rest.Serializer{}, rest.Serializer{},
200,
map[string]any{"a": 1, "b": 2, "c": "test"}, map[string]any{"a": 1, "b": 2, "c": "test"},
"fields=", "fields=",
`{"a":1,"b":2,"c":"test"}`, `{"a":1,"b":2,"c":"test"}`,
@ -37,6 +40,7 @@ func TestSerialize(t *testing.T) {
{ {
"missing fields", "missing fields",
rest.Serializer{}, rest.Serializer{},
200,
map[string]any{"a": 1, "b": 2, "c": "test"}, map[string]any{"a": 1, "b": 2, "c": "test"},
"fields=missing", "fields=missing",
`{}`, `{}`,
@ -44,6 +48,7 @@ func TestSerialize(t *testing.T) {
{ {
"non map response", "non map response",
rest.Serializer{}, rest.Serializer{},
200,
"test", "test",
"fields=a,b,test", "fields=a,b,test",
`"test"`, `"test"`,
@ -51,13 +56,39 @@ func TestSerialize(t *testing.T) {
{ {
"non slice of map response", "non slice of map response",
rest.Serializer{}, rest.Serializer{},
200,
[]any{"a", "b", "test"}, []any{"a", "b", "test"},
"fields=a,test", "fields=a,test",
`["a","b","test"]`, `["a","b","test"]`,
}, },
{
"map with no matching field",
rest.Serializer{},
200,
map[string]any{"a": 1, "b": 2, "c": "test"},
"fields=missing", // test individual fields trim
`{}`,
},
{
">299 response",
rest.Serializer{},
300,
map[string]any{"a": 1, "b": 2, "c": "test"},
"fields=missing",
`{"a":1,"b":2,"c":"test"}`,
},
{
"<200 response",
rest.Serializer{},
199,
map[string]any{"a": 1, "b": 2, "c": "test"},
"fields=missing",
`{"a":1,"b":2,"c":"test"}`,
},
{ {
"map with existing and missing fields", "map with existing and missing fields",
rest.Serializer{}, rest.Serializer{},
200,
map[string]any{"a": 1, "b": 2, "c": "test"}, map[string]any{"a": 1, "b": 2, "c": "test"},
"fields=a, c ,missing", // test individual fields trim "fields=a, c ,missing", // test individual fields trim
`{"a":1,"c":"test"}`, `{"a":1,"c":"test"}`,
@ -65,6 +96,7 @@ func TestSerialize(t *testing.T) {
{ {
"custom fields param", "custom fields param",
rest.Serializer{FieldsParam: "custom"}, rest.Serializer{FieldsParam: "custom"},
200,
map[string]any{"a": 1, "b": 2, "c": "test"}, map[string]any{"a": 1, "b": 2, "c": "test"},
"custom=a, c ,missing", // test individual fields trim "custom=a, c ,missing", // test individual fields trim
`{"a":1,"c":"test"}`, `{"a":1,"c":"test"}`,
@ -72,6 +104,7 @@ func TestSerialize(t *testing.T) {
{ {
"slice of maps with existing and missing fields", "slice of maps with existing and missing fields",
rest.Serializer{}, rest.Serializer{},
200,
[]any{ []any{
map[string]any{"a": 11, "b": 11, "c": "test1"}, map[string]any{"a": 11, "b": 11, "c": "test1"},
map[string]any{"a": 22, "b": 22, "c": "test2"}, map[string]any{"a": 22, "b": 22, "c": "test2"},
@ -82,6 +115,7 @@ func TestSerialize(t *testing.T) {
{ {
"nested fields with mixed map and any slices", "nested fields with mixed map and any slices",
rest.Serializer{}, rest.Serializer{},
200,
map[string]any{ map[string]any{
"a": 1, "a": 1,
"b": 2, "b": 2,
@ -139,6 +173,7 @@ func TestSerialize(t *testing.T) {
{ {
"SearchResult", "SearchResult",
rest.Serializer{}, rest.Serializer{},
200,
search.Result{ search.Result{
Page: 1, Page: 1,
PerPage: 10, PerPage: 10,
@ -155,6 +190,7 @@ func TestSerialize(t *testing.T) {
{ {
"*SearchResult", "*SearchResult",
rest.Serializer{}, rest.Serializer{},
200,
&search.Result{ &search.Result{
Page: 1, Page: 1,
PerPage: 10, PerPage: 10,
@ -171,25 +207,27 @@ func TestSerialize(t *testing.T) {
} }
for _, s := range scenarios { for _, s := range scenarios {
e := echo.New() t.Run(s.name, func(t *testing.T) {
req := httptest.NewRequest(http.MethodPost, "/", nil) req := httptest.NewRequest(http.MethodPost, "/", nil)
req.URL.RawQuery = s.query req.URL.RawQuery = s.query
rec := httptest.NewRecorder() rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
if err := s.serializer.Serialize(c, s.data, ""); err != nil { e := echo.New()
t.Errorf("[%s] Serialize failure: %v", s.name, err) c := e.NewContext(req, rec)
continue c.Response().Status = s.statusCode
}
rawBody, err := io.ReadAll(rec.Result().Body) if err := s.serializer.Serialize(c, s.data, ""); err != nil {
if err != nil { t.Fatalf("[%s] Serialize failure: %v", s.name, err)
t.Errorf("[%s] Failed to read request body: %v", s.name, err) }
continue
}
if v := strings.TrimSpace(string(rawBody)); v != s.expected { rawBody, err := io.ReadAll(rec.Result().Body)
t.Fatalf("[%s] Expected body\n%v \ngot: \n%v", s.name, s.expected, v) if err != nil {
} t.Fatalf("[%s] Failed to read request body: %v", s.name, err)
}
if v := strings.TrimSpace(string(rawBody)); v != s.expected {
t.Fatalf("[%s] Expected body\n%v \ngot: \n%v", s.name, s.expected, v)
}
})
} }
} }