diff --git a/binding/form.go b/binding/form.go index b17352ba..5c8b9723 100644 --- a/binding/form.go +++ b/binding/form.go @@ -7,6 +7,7 @@ package binding import ( "errors" "net/http" + "net/url" ) const defaultMemory = 32 << 20 @@ -32,6 +33,17 @@ func (formBinding) Bind(req *http.Request, obj any) error { return validate(obj) } +func (formBinding) BindBody(body []byte, obj any) error { + form, err := url.ParseQuery(string(body)) + if err != nil { + return err + } + if err := mapForm(obj, form); err != nil { + return err + } + return validate(obj) +} + func (formPostBinding) Name() string { return "form-urlencoded" } @@ -46,6 +58,17 @@ func (formPostBinding) Bind(req *http.Request, obj any) error { return validate(obj) } +func (formPostBinding) BindBody(body []byte, obj any) error { + form, err := url.ParseQuery(string(body)) + if err != nil { + return err + } + if err := mapForm(obj, form); err != nil { + return err + } + return validate(obj) +} + func (formMultipartBinding) Name() string { return "multipart/form-data" } @@ -60,3 +83,14 @@ func (formMultipartBinding) Bind(req *http.Request, obj any) error { return validate(obj) } + +func (formMultipartBinding) BindBody(body []byte, obj any) error { + form, err := url.ParseQuery(string(body)) + if err != nil { + return err + } + if err := mapForm(obj, form); err != nil { + return err + } + return validate(obj) +} diff --git a/binding/form_test.go b/binding/form_test.go new file mode 100644 index 00000000..5ea5757d --- /dev/null +++ b/binding/form_test.go @@ -0,0 +1,134 @@ +package binding + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_formMultipartBinding_BindBody(t *testing.T) { + type testObj struct { + Param int `form:"param"` + } + type args struct { + body []byte + obj any + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "test_no_error", + args: args{body: []byte(`param1=value1¶m2=value2`), obj: make(map[string]string)}, + wantErr: false, + }, + { + name: "test_parse_error", + args: args{body: []byte(`par;am1=value1`), obj: make(map[string]string)}, + wantErr: true, + }, + { + name: "test_mapForm_error", + args: args{body: []byte(`param=value1`), obj: &testObj{}}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f := formMultipartBinding{} + err := f.BindBody(tt.args.body, tt.args.obj) + if tt.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } +} + +func Test_formBinding_BindBody(t *testing.T) { + type testObj struct { + Param int `form:"param1"` + } + type args struct { + body []byte + obj any + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "test_no_error", + args: args{body: []byte(`param1=1¶m2=value2`), obj: &testObj{}}, + wantErr: false, + }, + { + name: "test_parse_error", + args: args{body: []byte(`par;am1=value1`), obj: make(map[string]string)}, + wantErr: true, + }, + { + name: "test_mapForm_error", + args: args{body: []byte(`param1=value1`), obj: &testObj{}}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f := formBinding{} + err := f.BindBody(tt.args.body, tt.args.obj) + if tt.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } +} + +func Test_formPostBinding_BindBody(t *testing.T) { + type testObj struct { + Param int `form:"param1"` + } + type args struct { + body []byte + obj any + } + tests := []struct { + name string + f formPostBinding + args args + wantErr bool + }{ + { + name: "test_no_error", + args: args{body: []byte(`param1=1¶m2=value2`), obj: &testObj{}}, + wantErr: false, + }, + { + name: "test_parse_error", + args: args{body: []byte(`par;am1=value1`), obj: make(map[string]string)}, + wantErr: true, + }, + { + name: "test_mapForm_error", + args: args{body: []byte(`param1=value1`), obj: &testObj{}}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f := formPostBinding{} + err := f.BindBody(tt.args.body, tt.args.obj) + if tt.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } +}