Skip to content

Commit

Permalink
fix #3245 (#3298)
Browse files Browse the repository at this point in the history
  • Loading branch information
oldme-git authored Feb 6, 2024
1 parent e1fa990 commit 51326f3
Show file tree
Hide file tree
Showing 12 changed files with 102 additions and 29 deletions.
3 changes: 2 additions & 1 deletion database/gdb/gdb_func.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gmeta"
"github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/v2/util/gutil"
)

Expand Down Expand Up @@ -70,7 +71,7 @@ var (
quoteWordReg = regexp.MustCompile(`^[a-zA-Z0-9\-_]+$`)

// structTagPriority tags for struct converting for orm field mapping.
structTagPriority = append([]string{OrmTagForStruct}, gconv.StructTagPriority...)
structTagPriority = append([]string{OrmTagForStruct}, gtag.StructTagPriority...)
)

// WithDB injects given db object into context and returns a new context.
Expand Down
5 changes: 3 additions & 2 deletions net/ghttp/ghttp_request_param_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ func (r *Request) doGetRequestStruct(pointer interface{}, mapping ...map[string]
if err = r.mergeInTagStructValue(data, pointer); err != nil {
return data, nil
}

return data, gconv.Struct(data, pointer, mapping...)
}

Expand Down Expand Up @@ -262,7 +263,7 @@ func (r *Request) mergeInTagStructValue(data map[string]interface{}, pointer int
if tagValue := field.TagIn(); tagValue != "" {
switch tagValue {
case goai.ParameterInHeader:
foundHeaderKey, foundHeaderValue := gutil.MapPossibleItemByKey(headerMap, field.Name())
foundHeaderKey, foundHeaderValue := gutil.MapPossibleItemByKey(headerMap, field.TagPriorityName())
if foundHeaderKey != "" {
foundKey, foundValue = gutil.MapPossibleItemByKey(data, foundHeaderKey)
if foundKey == "" {
Expand All @@ -274,7 +275,7 @@ func (r *Request) mergeInTagStructValue(data map[string]interface{}, pointer int
}
}
case goai.ParameterInCookie:
foundCookieKey, foundCookieValue := gutil.MapPossibleItemByKey(cookieMap, field.Name())
foundCookieKey, foundCookieValue := gutil.MapPossibleItemByKey(cookieMap, field.TagPriorityName())
if foundCookieKey != "" {
foundKey, foundValue = gutil.MapPossibleItemByKey(data, foundCookieKey)
if foundKey == "" {
Expand Down
44 changes: 44 additions & 0 deletions net/ghttp/ghttp_z_unit_issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -524,3 +524,47 @@ func Test_Issue2457(t *testing.T) {
t.Assert(c.GetContent(ctx, "/list"), `{"code":0,"message":"","data":{"Code":100,"Data":{"Title":"title","Content":"hello"},"Msg":""}}`)
})
}

// https://github.com/gogf/gf/issues/3245
type Issue3245Req struct {
g.Meta `path:"/hello" method:"get"`
Name string `p:"nickname" json:"name"`
XHeaderName string `p:"Header-Name" in:"header" json:"X-Header-Name"`
XHeaderAge uint8 `p:"Header-Age" in:"cookie" json:"X-Header-Age"`
}
type Issue3245Res struct {
Reply any
}

type Issue3245V1 struct{}

func (Issue3245V1) Hello(ctx context.Context, req *Issue3245Req) (res *Issue3245Res, err error) {
res = &Issue3245Res{
Reply: req,
}
return
}

func Test_Issue3245(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
s := g.Server(guid.S())
s.Use(ghttp.MiddlewareHandlerResponse)
s.Group("/", func(group *ghttp.RouterGroup) {
group.Bind(
new(Issue3245V1),
)
})
s.SetDumpRouterMap(false)
s.Start()
defer s.Shutdown()
time.Sleep(100 * time.Millisecond)

c := g.Client()
c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
c.SetHeader("Header-Name", "oldme")
c.SetCookie("Header-Age", "25")

expect := `{"code":0,"message":"","data":{"Reply":{"name":"oldme","X-Header-Name":"oldme","X-Header-Age":25}}}`
t.Assert(c.GetContent(ctx, "/hello?nickname=oldme"), expect)
})
}
9 changes: 1 addition & 8 deletions net/goai/goai_parameter_ref.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/os/gstructs"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
)

// Parameters is specified by OpenAPI/Swagger 3.0 standard.
Expand All @@ -30,14 +29,8 @@ type ParameterRef struct {
func (oai *OpenApiV3) newParameterRefWithStructMethod(field gstructs.Field, path, method string) (*ParameterRef, error) {
var (
tagMap = field.TagMap()
fieldName = field.Name()
fieldName = field.TagPriorityName()
)
for _, tagName := range gconv.StructTagPriority {
if tagValue := field.Tag(tagName); tagValue != "" {
fieldName = tagValue
break
}
}
fieldName = gstr.Split(gstr.Trim(fieldName), ",")[0]
if fieldName == "" {
fieldName = field.Name()
Expand Down
8 changes: 1 addition & 7 deletions net/goai/goai_shema.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,7 @@ func (oai *OpenApiV3) structToSchema(object interface{}) (*Schema, error) {
if !gstr.IsLetterUpper(structField.Name()[0]) {
continue
}
var fieldName = structField.Name()
for _, tagName := range gconv.StructTagPriority {
if tagValue := structField.Tag(tagName); tagValue != "" {
fieldName = tagValue
break
}
}
var fieldName = structField.TagPriorityName()
fieldName = gstr.Split(gstr.Trim(fieldName), ",")[0]
if fieldName == "" {
fieldName = structField.Name()
Expand Down
6 changes: 3 additions & 3 deletions os/gstructs/gstructs.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ type FieldMapInput struct {
type RecursiveOption int

const (
RecursiveOptionNone RecursiveOption = 0 // No recursively retrieving fields as map if the field is an embedded struct.
RecursiveOptionEmbedded RecursiveOption = 1 // Recursively retrieving fields as map if the field is an embedded struct.
RecursiveOptionEmbeddedNoTag RecursiveOption = 2 // Recursively retrieving fields as map if the field is an embedded struct and the field has no tag.
RecursiveOptionNone RecursiveOption = iota // No recursively retrieving fields as map if the field is an embedded struct.
RecursiveOptionEmbedded // Recursively retrieving fields as map if the field is an embedded struct.
RecursiveOptionEmbeddedNoTag // Recursively retrieving fields as map if the field is an embedded struct and the field has no tag.
)

// Fields retrieves and returns the fields of `pointer` as slice.
Expand Down
13 changes: 13 additions & 0 deletions os/gstructs/gstructs_field_tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,16 @@ func (f *Field) TagIn() string {
v := f.Tag(gtag.In)
return v
}

// TagPriorityName checks and returns tag name that matches the name item in `gtag.StructTagPriority`.
// It or else returns attribute field Name if it doesn't have a tag name by `gtag.StructsTagPriority`.
func (f *Field) TagPriorityName() string {
var name = f.Name()
for _, tagName := range gtag.StructTagPriority {
if tagValue := f.Tag(tagName); tagValue != "" {
name = tagValue
break
}
}
return name
}
20 changes: 20 additions & 0 deletions os/gstructs/gstructs_z_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -527,3 +527,23 @@ func TestType_TagExample(t *testing.T) {
t.Assert(r[1].TagExample(), `john`)
})
}

func Test_Fields_TagPriorityName(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type User struct {
Name string `gconv:"name_gconv" c:"name_c"`
Age uint `p:"name_p" param:"age_param"`
Pass string `json:"pass_json"`
IsMen bool
}
var user *User
fields, _ := gstructs.Fields(gstructs.FieldsInput{
Pointer: user,
RecursiveOption: 0,
})
t.Assert(fields[0].TagPriorityName(), "name_gconv")
t.Assert(fields[1].TagPriorityName(), "age_param")
t.Assert(fields[2].TagPriorityName(), "pass_json")
t.Assert(fields[3].TagPriorityName(), "IsMen")
})
}
4 changes: 1 addition & 3 deletions util/gconv/gconv.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@ var (
// StructTagPriority defines the default priority tags for Map*/Struct* functions.
// Note that, the `gconv/param` tags are used by old version of package.
// It is strongly recommended using short tag `c/p` instead in the future.
StructTagPriority = []string{
gtag.GConv, gtag.Param, gtag.GConvShort, gtag.ParamShort, gtag.Json,
}
StructTagPriority = gtag.StructTagPriority
)

// Byte converts `any` to byte.
Expand Down
7 changes: 4 additions & 3 deletions util/gconv/gconv_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/gogf/gf/v2/internal/empty"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/utils"
"github.com/gogf/gf/v2/util/gtag"
)

type recursiveType string
Expand Down Expand Up @@ -72,7 +73,7 @@ func doMapConvert(value interface{}, recursive recursiveType, mustMapReturn bool

var (
usedOption = getUsedMapOption(option...)
newTags = StructTagPriority
newTags = gtag.StructTagPriority
)
if usedOption.Deep {
recursive = recursiveTypeTrue
Expand All @@ -81,9 +82,9 @@ func doMapConvert(value interface{}, recursive recursiveType, mustMapReturn bool
case 0:
// No need handling.
case 1:
newTags = append(strings.Split(usedOption.Tags[0], ","), StructTagPriority...)
newTags = append(strings.Split(usedOption.Tags[0], ","), gtag.StructTagPriority...)
default:
newTags = append(usedOption.Tags, StructTagPriority...)
newTags = append(usedOption.Tags, gtag.StructTagPriority...)
}
// Assert the common combination of types, and finally it uses reflection.
dataMap := make(map[string]interface{})
Expand Down
5 changes: 3 additions & 2 deletions util/gconv/gconv_struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/utils"
"github.com/gogf/gf/v2/os/gstructs"
"github.com/gogf/gf/v2/util/gtag"
)

// Struct maps the params key-value pairs to the corresponding struct object's attributes.
Expand Down Expand Up @@ -271,9 +272,9 @@ func doStruct(params interface{}, pointer interface{}, paramKeyToAttrMap map[str
priorityTagArray []string
)
if priorityTag != "" {
priorityTagArray = append(utils.SplitAndTrim(priorityTag, ","), StructTagPriority...)
priorityTagArray = append(utils.SplitAndTrim(priorityTag, ","), gtag.StructTagPriority...)
} else {
priorityTagArray = StructTagPriority
priorityTagArray = gtag.StructTagPriority
}
tagToAttrNameMap, err := gstructs.TagMapName(pointerElemReflectValue, priorityTagArray)
if err != nil {
Expand Down
7 changes: 7 additions & 0 deletions util/gtag/gtag.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,10 @@ const (
Security = "security" // Security defines scheme for authentication. Detail to see https://swagger.io/docs/specification/authentication/
In = "in" // Swagger distinguishes between the following parameter types based on the parameter location. Detail to see https://swagger.io/docs/specification/describing-parameters/
)

// StructTagPriority defines the default priority tags for Map*/Struct* functions.
// Note that, the `gconv/param` tags are used by old version of package.
// It is strongly recommended using short tag `c/p` instead in the future.
var StructTagPriority = []string{
GConv, Param, GConvShort, ParamShort, Json,
}

0 comments on commit 51326f3

Please sign in to comment.