Repository: go-kratos/kratos
Pull request #2256 (2022-08-04 07:00:11)

fix: in case url or form bind param error should return BadRequest
in case url or form bind param error should return BadRequest


Patch:
diff --git a/transport/http/binding/bind.go b/transport/http/binding/bind.go
index 3155d61e..10007367 100644
--- a/transport/http/binding/bind.go
+++ b/transport/http/binding/bind.go
@@ -4,13 +4,18 @@ import (
 	"net/http"
 	"net/url"
 
+	"github.com/go-kratos/kratos/v2/errors"
+
 	"github.com/go-kratos/kratos/v2/encoding"
 	"github.com/go-kratos/kratos/v2/encoding/form"
 )
 
 // BindQuery bind vars parameters to target.
 func BindQuery(vars url.Values, target interface{}) error {
-	return encoding.GetCodec(form.Name).Unmarshal([]byte(vars.Encode()), target)
+	if err := encoding.GetCodec(form.Name).Unmarshal([]byte(vars.Encode()), target); err != nil {
+		return errors.BadRequest("CODEC", err.Error())
+	}
+	return nil
 }
 
 // BindForm bind form parameters to target.
@@ -18,5 +23,8 @@ func BindForm(req *http.Request, target interface{}) error {
 	if err := req.ParseForm(); err != nil {
 		return err
 	}
-	return encoding.GetCodec(form.Name).Unmarshal([]byte(req.Form.Encode()), target)
+	if err := encoding.GetCodec(form.Name).Unmarshal([]byte(req.Form.Encode()), target); err != nil {
+		return errors.BadRequest("CODEC", err.Error())
+	}
+	return nil
 }


Test patch:
diff --git a/transport/http/binding/bind_test.go b/transport/http/binding/bind_test.go
index 5e2552f9..20aadba7 100644
--- a/transport/http/binding/bind_test.go
+++ b/transport/http/binding/bind_test.go
@@ -7,6 +7,8 @@ import (
 	"reflect"
 	"strings"
 	"testing"
+
+	"github.com/go-kratos/kratos/v2/errors"
 )
 
 func TestBindQuery(t *testing.T) {
@@ -14,7 +16,12 @@ func TestBindQuery(t *testing.T) {
 		Name string `json:"name"`
 		URL  string `json:"url"`
 	}
+
+	type TestBind2 struct {
+		Age int `json:"age"`
+	}
 	p1 := TestBind{}
+	p2 := TestBind2{}
 	type args struct {
 		vars   url.Values
 		target interface{}
@@ -34,11 +41,31 @@ func TestBindQuery(t *testing.T) {
 			wantErr: false,
 			want:    &TestBind{"kratos", "https://go-kratos.dev/"},
 		},
+		{
+			name: "test1",
+			args: args{
+				vars:   map[string][]string{"age": {"kratos"}, "url": {"https://go-kratos.dev/"}},
+				target: &p2,
+			},
+			wantErr: true,
+			want:    errors.BadRequest("CODEC", ""),
+		},
+		{
+			name: "test2",
+			args: args{
+				vars:   map[string][]string{"age": {"1"}, "url": {"https://go-kratos.dev/"}},
+				target: &TestBind2{},
+			},
+			wantErr: false,
+			want:    &TestBind2{Age: 1},
+		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			if err := BindQuery(tt.args.vars, tt.args.target); (err != nil) != tt.wantErr {
 				t.Errorf("BindQuery() error = %v, wantErr %v", err, tt.wantErr)
+			} else {
+				t.Log(err)
 			}
 			if !tt.wantErr && !reflect.DeepEqual(tt.args.target, tt.want) {
 				t.Errorf("BindQuery() target = %v, want %v", tt.args.target, tt.want)
@@ -52,6 +79,9 @@ func TestBindForm(t *testing.T) {
 		Name string `json:"name"`
 		URL  string `json:"url"`
 	}
+	type TestBind2 struct {
+		Age int `json:"age"`
+	}
 	p1 := TestBind{}
 	type args struct {
 		req    *http.Request
@@ -85,6 +115,19 @@ func TestBindForm(t *testing.T) {
 			wantErr: false,
 			want:    &TestBind{"kratos", "https://go-kratos.dev/"},
 		},
+		{
+			name: "error BadRequest",
+			args: args{
+				req: &http.Request{
+					Method: "POST",
+					Header: http.Header{"Content-Type": {"application/x-www-form-urlencoded; param=value"}},
+					Body:   io.NopCloser(strings.NewReader("age=a")),
+				},
+				target: &TestBind2{},
+			},
+			wantErr: true,
+			want:    nil,
+		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
@@ -92,6 +135,7 @@ func TestBindForm(t *testing.T) {
 			if (err != nil) != tt.wantErr {
 				t.Errorf("BindForm() error = %v, wantErr %v", err, tt.wantErr)
 			}
+			t.Log(err)
 			if !tt.wantErr && !reflect.DeepEqual(tt.args.target, tt.want) {
 				t.Errorf("BindForm() target = %v, want %v", tt.args.target, tt.want)
 			}