fix(binding): support query tag in query binding while maintaining form tag backward compatibility

Co-authored-by: appleboy <21979+appleboy@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2025-09-21 09:54:59 +00:00
parent 6800098da5
commit 33581e60a4
3 changed files with 73 additions and 1 deletions

View File

@ -35,6 +35,23 @@ func mapForm(ptr any, form map[string][]string) error {
return mapFormByTag(ptr, form, "form")
}
func mapQuery(ptr any, form map[string][]string) error {
// Try binding with "query" tags first (logical behavior)
err := mapFormByTag(ptr, form, "query")
if err != nil {
return err
}
// For backward compatibility, also try "form" tags
// This allows mixed usage and maintains compatibility
err = mapFormByTag(ptr, form, "form")
if err != nil {
return err
}
return nil
}
func MapFormWithTag(ptr any, form map[string][]string, tag string) error {
return mapFormByTag(ptr, form, tag)
}

View File

@ -14,7 +14,7 @@ func (queryBinding) Name() string {
func (queryBinding) Bind(req *http.Request, obj any) error {
values := req.URL.Query()
if err := mapForm(obj, values); err != nil {
if err := mapQuery(obj, values); err != nil {
return err
}
return validate(obj)

55
binding/query_test.go Normal file
View File

@ -0,0 +1,55 @@
package binding
import (
"net/http"
"net/url"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestQueryBindingWithQueryTag(t *testing.T) {
var s struct {
Foo string `query:"foo"`
Bar string `query:"bar"`
}
request := &http.Request{URL: &url.URL{RawQuery: "foo=HELLO&bar=WORLD"}}
err := queryBinding{}.Bind(request, &s)
require.NoError(t, err)
assert.Equal(t, "HELLO", s.Foo)
assert.Equal(t, "WORLD", s.Bar)
}
func TestQueryBindingWithFormTag(t *testing.T) {
var s struct {
Foo string `form:"foo"`
Bar string `form:"bar"`
}
request := &http.Request{URL: &url.URL{RawQuery: "foo=HELLO&bar=WORLD"}}
err := queryBinding{}.Bind(request, &s)
require.NoError(t, err)
assert.Equal(t, "HELLO", s.Foo)
assert.Equal(t, "WORLD", s.Bar)
}
func TestQueryBindingMixedTags(t *testing.T) {
var s struct {
Foo string `query:"foo"`
Bar string `form:"bar"`
}
request := &http.Request{URL: &url.URL{RawQuery: "foo=HELLO&bar=WORLD"}}
err := queryBinding{}.Bind(request, &s)
require.NoError(t, err)
assert.Equal(t, "HELLO", s.Foo)
assert.Equal(t, "WORLD", s.Bar)
}