Skip to content

Commit

Permalink
fix: do not pre-bind for BindXXX interface & normalize content-type (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
FGYFFFF authored Feb 19, 2024
1 parent 532011f commit c528e17
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 8 deletions.
2 changes: 1 addition & 1 deletion pkg/app/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -1458,7 +1458,7 @@ func (ctx *RequestContext) BindByContentType(obj interface{}) error {
return ctx.BindQuery(obj)
}
ct := utils.FilterContentType(bytesconv.B2s(ctx.Request.Header.ContentType()))
switch ct {
switch strings.ToLower(ct) {
case consts.MIMEApplicationJSON:
return ctx.BindJSON(obj)
case consts.MIMEPROTOBUF:
Expand Down
42 changes: 42 additions & 0 deletions pkg/app/server/binding/binder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1549,6 +1549,48 @@ func TestBind_Issue1015(t *testing.T) {
assert.DeepEqual(t, "asd", result.A)
}

func TestBind_WithoutPreBindForTag(t *testing.T) {
type BaseQuery struct {
Action string `query:"Action" binding:"required"`
Version string `query:"Version" binding:"required"`
}

req := newMockRequest().
SetJSONContentType().
SetRequestURI("http://foobar.com/?Action=action&Version=version").
SetBody([]byte(``))

var result BaseQuery

err := DefaultBinder().BindQuery(req.Req, &result)
if err != nil {
t.Error(err)
}
assert.DeepEqual(t, "action", result.Action)
assert.DeepEqual(t, "version", result.Version)
}

func TestBind_NormalizeContentType(t *testing.T) {
type BaseQuery struct {
Action string `json:"action" binding:"required"`
Version string `json:"version" binding:"required"`
}

req := newMockRequest().
SetHeader("Content-Type", "ApplicAtion/json").
SetRequestURI("http://foobar.com/?Action=action&Version=version").
SetBody([]byte(`{"action":"action", "version":"version"}`))

var result BaseQuery

err := DefaultBinder().BindQuery(req.Req, &result)
if err != nil {
t.Error(err)
}
assert.DeepEqual(t, "action", result.Action)
assert.DeepEqual(t, "version", result.Version)
}

func Benchmark_Binding(b *testing.B) {
type Req struct {
Version string `path:"v"`
Expand Down
13 changes: 8 additions & 5 deletions pkg/app/server/binding/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import (
"io"
"net/url"
"reflect"
"strings"
"sync"

exprValidator "github.com/bytedance/go-tagexpr/v2/validator"
Expand Down Expand Up @@ -175,9 +176,11 @@ func (b *defaultBinder) bindTag(req *protocol.Request, v interface{}, params par
return b.bindNonStruct(req, v)
}

err := b.preBindBody(req, v)
if err != nil {
return fmt.Errorf("bind body failed, err=%v", err)
if len(tag) == 0 {
err := b.preBindBody(req, v)
if err != nil {
return fmt.Errorf("bind body failed, err=%v", err)
}
}
cache := b.tagCache(tag)
cached, ok := cache.Load(typeID)
Expand Down Expand Up @@ -323,7 +326,7 @@ func (b *defaultBinder) preBindBody(req *protocol.Request, v interface{}) error
return nil
}
ct := bytesconv.B2s(req.Header.ContentType())
switch utils.FilterContentType(ct) {
switch strings.ToLower(utils.FilterContentType(ct)) {
case consts.MIMEApplicationJSON:
return hJson.Unmarshal(req.Body(), v)
case consts.MIMEPROTOBUF:
Expand All @@ -339,7 +342,7 @@ func (b *defaultBinder) preBindBody(req *protocol.Request, v interface{}) error

func (b *defaultBinder) bindNonStruct(req *protocol.Request, v interface{}) (err error) {
ct := bytesconv.B2s(req.Header.ContentType())
switch utils.FilterContentType(ct) {
switch strings.ToLower(utils.FilterContentType(ct)) {
case consts.MIMEApplicationJSON:
err = hJson.Unmarshal(req.Body(), v)
case consts.MIMEPROTOBUF:
Expand Down
2 changes: 1 addition & 1 deletion pkg/app/server/binding/internal/decoder/gjson_required.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func checkRequireJSON(req *protocol.Request, tagInfo TagInfo) bool {
return true
}
ct := bytesconv.B2s(req.Header.ContentType())
if utils.FilterContentType(ct) != consts.MIMEApplicationJSON {
if !strings.EqualFold(utils.FilterContentType(ct), consts.MIMEApplicationJSON) {
return false
}
result := gjson.GetBytes(req.Body(), tagInfo.JSONName)
Expand Down
2 changes: 1 addition & 1 deletion pkg/app/server/binding/internal/decoder/sonic_required.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func checkRequireJSON(req *protocol.Request, tagInfo TagInfo) bool {
return true
}
ct := bytesconv.B2s(req.Header.ContentType())
if utils.FilterContentType(ct) != consts.MIMEApplicationJSON {
if !strings.EqualFold(utils.FilterContentType(ct), consts.MIMEApplicationJSON) {
return false
}
node, _ := sonic.Get(req.Body(), stringSliceForInterface(tagInfo.JSONName)...)
Expand Down

0 comments on commit c528e17

Please sign in to comment.