Skip to content

Commit f8331ba

Browse files
authored
feat(net/ghttp): add Request.GetMetaTag to retrieve specific meta tag value (#4185)
1 parent bcda48b commit f8331ba

File tree

6 files changed

+96
-15
lines changed

6 files changed

+96
-15
lines changed

.github/workflows/ci-main.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
coverage=$1
44

55
# update code of submodules
6-
make subup
6+
git clone https://github.com/gogf/examples
77

88
# find all path that contains go.mod.
99
for file in `find . -name go.mod`; do
@@ -22,14 +22,14 @@ for file in `find . -name go.mod`; do
2222
fi
2323

2424
# Check if it's a contrib directory or examples directory
25-
if [[ $dirpath =~ "/contrib/" ]] || [ "examples" = $(basename $dirpath) ]; then
25+
if [[ $dirpath =~ "/contrib/" ]] || [[ $dirpath =~ "/examples/" ]]; then
2626
# Check if go version meets the requirement
2727
if ! go version | grep -qE "go${LATEST_GO_VERSION}"; then
2828
echo "ignore path $dirpath as go version is not ${LATEST_GO_VERSION}: $(go version)"
2929
continue 1
3030
fi
3131
# If it's examples directory, only build without tests
32-
if [ "examples" = $(basename $dirpath) ]; then
32+
if [[ $dirpath =~ "/examples/" ]]; then
3333
echo "the examples directory only needs to be built, not unit tests and coverage tests."
3434
cd $dirpath
3535
go mod tidy

net/ghttp/ghttp_request.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/gogf/gf/v2/os/gview"
2020
"github.com/gogf/gf/v2/text/gregex"
2121
"github.com/gogf/gf/v2/text/gstr"
22+
"github.com/gogf/gf/v2/util/gmeta"
2223
"github.com/gogf/gf/v2/util/guid"
2324
)
2425

@@ -40,7 +41,7 @@ type Request struct {
4041
// =================================================================================================================
4142

4243
handlers []*HandlerItemParsed // All matched handlers containing handler, hook and middleware for this request.
43-
serveHandler *HandlerItemParsed // Real handler serving for this request, not hook or middleware.
44+
serveHandler *HandlerItemParsed // Real business handler serving for this request, not hook or middleware handler.
4445
handlerResponse interface{} // Handler response object for Request/Response handler.
4546
hasHookHandler bool // A bool marking whether there's hook handler in the handlers for performance purpose.
4647
hasServeHandler bool // A bool marking whether there's serving handler in the handlers for performance purpose.
@@ -288,3 +289,25 @@ func (r *Request) GetHandlerResponse() interface{} {
288289
func (r *Request) GetServeHandler() *HandlerItemParsed {
289290
return r.serveHandler
290291
}
292+
293+
// GetMetaTag retrieves and returns the metadata value associated with the given key from the request struct.
294+
// The meta value is from struct tags from g.Meta/gmeta.Meta type.
295+
// For example:
296+
//
297+
// type GetMetaTagReq struct {
298+
// g.Meta `path:"/test" method:"post" summary:"meta_tag" tags:"meta"`
299+
// // ...
300+
// }
301+
//
302+
// r.GetMetaTag("summary") // returns "meta_tag"
303+
// r.GetMetaTag("method") // returns "post"
304+
func (r *Request) GetMetaTag(key string) string {
305+
if r.serveHandler == nil || r.serveHandler.Handler == nil {
306+
return ""
307+
}
308+
metaValue := gmeta.Get(r.serveHandler.Handler.Info.Type.In(1), key)
309+
if metaValue != nil {
310+
return metaValue.String()
311+
}
312+
return ""
313+
}

net/ghttp/ghttp_z_unit_feature_request_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package ghttp_test
88

99
import (
1010
"bytes"
11+
"context"
1112
"fmt"
1213
"io"
1314
"testing"
@@ -861,3 +862,43 @@ func Test_Params_GetRequestMapStrVar(t *testing.T) {
861862
t.Assert(client.GetContent(ctx, "/GetRequestMapStrVar", "id=1"), 1)
862863
})
863864
}
865+
866+
type GetMetaTagReq struct {
867+
g.Meta `path:"/test" method:"post" summary:"meta_tag" tags:"meta"`
868+
Name string
869+
}
870+
type GetMetaTagRes struct{}
871+
872+
type GetMetaTagSt struct{}
873+
874+
func (r GetMetaTagSt) PostTest(ctx context.Context, req *GetMetaTagReq) (*GetMetaTagRes, error) {
875+
return &GetMetaTagRes{}, nil
876+
}
877+
878+
func TestRequest_GetMetaTag(t *testing.T) {
879+
s := g.Server(guid.S())
880+
s.Use(func(r *ghttp.Request) {
881+
r.Response.Writef(
882+
"summary:%s,method:%s",
883+
r.GetMetaTag("summary"), r.GetMetaTag("method"),
884+
)
885+
})
886+
s.Group("/", func(grp *ghttp.RouterGroup) {
887+
grp.Bind(GetMetaTagSt{})
888+
})
889+
s.SetDumpRouterMap(false)
890+
s.Start()
891+
defer s.Shutdown()
892+
time.Sleep(1000 * time.Millisecond)
893+
894+
s.SetDumpRouterMap(false)
895+
s.Start()
896+
defer s.Shutdown()
897+
time.Sleep(100 * time.Millisecond)
898+
899+
gtest.C(t, func(t *gtest.T) {
900+
client := g.Client()
901+
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
902+
t.Assert(client.PostContent(ctx, "/test", "name=john"), "summary:meta_tag,method:post")
903+
})
904+
}

os/gstructs/gstructs.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ type Field struct {
3636
type FieldsInput struct {
3737
// Pointer should be type of struct/*struct.
3838
// TODO this attribute name is not suitable, which would make confuse.
39-
Pointer interface{}
39+
Pointer any
4040

4141
// RecursiveOption specifies the way retrieving the fields recursively if the attribute
4242
// is an embedded struct. It is RecursiveOptionNone in default.
@@ -47,7 +47,7 @@ type FieldsInput struct {
4747
type FieldMapInput struct {
4848
// Pointer should be type of struct/*struct.
4949
// TODO this attribute name is not suitable, which would make confuse.
50-
Pointer interface{}
50+
Pointer any
5151

5252
// PriorityTagArray specifies the priority tag array for retrieving from high to low.
5353
// If it's given `nil`, it returns map[name]Field, of which the `name` is attribute name.
@@ -123,6 +123,7 @@ func Fields(in FieldsInput) ([]Field, error) {
123123
}
124124
}
125125
continue
126+
default:
126127
}
127128
}
128129
continue
@@ -194,6 +195,7 @@ func FieldMap(in FieldMapInput) (map[string]Field, error) {
194195
mapField[k] = tempV
195196
}
196197
}
198+
default:
197199
}
198200
} else {
199201
mapField[field.Name()] = tempField
@@ -205,7 +207,19 @@ func FieldMap(in FieldMapInput) (map[string]Field, error) {
205207

206208
// StructType retrieves and returns the struct Type of specified struct/*struct.
207209
// The parameter `object` should be either type of struct/*struct/[]struct/[]*struct.
208-
func StructType(object interface{}) (*Type, error) {
210+
func StructType(object any) (*Type, error) {
211+
// if already reflect.Type
212+
if reflectType, ok := object.(reflect.Type); ok {
213+
for reflectType.Kind() == reflect.Ptr {
214+
reflectType = reflectType.Elem()
215+
}
216+
if reflectType.Kind() == reflect.Struct {
217+
return &Type{
218+
Type: reflectType,
219+
}, nil
220+
}
221+
}
222+
209223
var (
210224
reflectValue reflect.Value
211225
reflectKind reflect.Kind

util/gmeta/gmeta.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,37 @@
88
package gmeta
99

1010
import (
11+
"reflect"
12+
1113
"github.com/gogf/gf/v2/container/gvar"
1214
"github.com/gogf/gf/v2/os/gstructs"
1315
)
1416

1517
// Meta is used as an embedded attribute for struct to enabled metadata feature.
1618
type Meta struct{}
1719

18-
const (
19-
metaAttributeName = "Meta" // metaAttributeName is the attribute name of metadata in struct.
20-
metaTypeName = "gmeta.Meta" // metaTypeName is for type string comparison.
21-
)
20+
// metaAttributeName is the attribute name of metadata in struct.
21+
const metaAttributeName = "Meta"
22+
23+
// metaType holds the reflection. Type of Meta, used for efficient type comparison.
24+
var metaType = reflect.TypeOf(Meta{})
2225

2326
// Data retrieves and returns all metadata from `object`.
24-
func Data(object interface{}) map[string]string {
27+
func Data(object any) map[string]string {
2528
reflectType, err := gstructs.StructType(object)
2629
if err != nil {
2730
return nil
2831
}
2932
if field, ok := reflectType.FieldByName(metaAttributeName); ok {
30-
if field.Type.String() == metaTypeName {
33+
if field.Type == metaType {
3134
return gstructs.ParseTag(string(field.Tag))
3235
}
3336
}
3437
return map[string]string{}
3538
}
3639

3740
// Get retrieves and returns specified metadata by `key` from `object`.
38-
func Get(object interface{}, key string) *gvar.Var {
41+
func Get(object any, key string) *gvar.Var {
3942
v, ok := Data(object)[key]
4043
if !ok {
4144
return nil

0 commit comments

Comments
 (0)