From 53a74759a5743188e3a64e23cf1e8857cdd4bd5f Mon Sep 17 00:00:00 2001 From: Kevin Wan Date: Tue, 5 Nov 2024 22:09:30 +0800 Subject: [PATCH] feat: support json array in request body (#4444) --- rest/httpx/requests.go | 20 ++++++++++++-------- rest/httpx/requests_test.go | 22 +++++++++++++++++++++- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/rest/httpx/requests.go b/rest/httpx/requests.go index c6199a83..87c576a9 100644 --- a/rest/httpx/requests.go +++ b/rest/httpx/requests.go @@ -3,6 +3,7 @@ package httpx import ( "io" "net/http" + "reflect" "strings" "sync/atomic" @@ -43,16 +44,19 @@ type Validator interface { // Parse parses the request. func Parse(r *http.Request, v any) error { - if err := ParsePath(r, v); err != nil { - return err - } + kind := mapping.Deref(reflect.TypeOf(v)).Kind() + if kind != reflect.Array && kind != reflect.Slice { + if err := ParsePath(r, v); err != nil { + return err + } - if err := ParseForm(r, v); err != nil { - return err - } + if err := ParseForm(r, v); err != nil { + return err + } - if err := ParseHeaders(r, v); err != nil { - return err + if err := ParseHeaders(r, v); err != nil { + return err + } } if err := ParseJsonBody(r, v); err != nil { diff --git a/rest/httpx/requests_test.go b/rest/httpx/requests_test.go index 02b7164a..437b9a13 100644 --- a/rest/httpx/requests_test.go +++ b/rest/httpx/requests_test.go @@ -325,11 +325,31 @@ func TestParseJsonBody(t *testing.T) { r := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(body)) r.Header.Set(ContentType, header.JsonContentType) - assert.NoError(t, ParseJsonBody(r, &v)) + assert.NoError(t, Parse(r, &v)) assert.Equal(t, 1, len(v)) assert.Equal(t, "kevin", v[0].Name) assert.Equal(t, 18, v[0].Age) }) + + t.Run("form and array body", func(t *testing.T) { + var v []struct { + // we can only ignore the form tag, + // because if the value is a slice, it should be in the body, + // but it's hard to detect when we treat it as a json body. + Product string `form:"product"` + Name string `json:"name"` + Age int `json:"age"` + } + + body := `[{"name":"apple", "age": 18}]` + r := httptest.NewRequest(http.MethodPost, "/a?product=tree", strings.NewReader(body)) + r.Header.Set(ContentType, header.JsonContentType) + + assert.NoError(t, Parse(r, &v)) + assert.Equal(t, 1, len(v)) + assert.Equal(t, "apple", v[0].Name) + assert.Equal(t, 18, v[0].Age) + }) } func TestParseRequired(t *testing.T) {