Araneae: integrate custom context interfaces into Gin
Some checks are pending
CodeQL / Analyze (go) (push) Waiting to run
Run Tests / lint (push) Waiting to run
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, ) (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -race) (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -tags "sonic avx") (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -tags go_json) (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -tags nomsgpack) (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, ) (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -race) (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -tags "sonic avx") (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -tags go_json) (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -tags nomsgpack) (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, ) (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -race) (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -tags "sonic avx") (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -tags go_json) (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -tags nomsgpack) (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, ) (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -race) (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -tags "sonic avx") (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -tags go_json) (push) Blocked by required conditions
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -tags nomsgpack) (push) Blocked by required conditions

This commit is contained in:
Muyao CHEN 2024-09-28 10:22:47 +02:00
parent f05f966a08
commit 116d0b112e
5 changed files with 401 additions and 3 deletions

8
araneae_context.go Normal file
View File

@ -0,0 +1,8 @@
package gin
import "golang.org/x/net/context"
// BaseContext gets the basic context of the request
func (ctx *Context) BaseContext() context.Context {
return ctx.Request.Context()
}

310
araneae_request.go Normal file
View File

@ -0,0 +1,310 @@
package gin
import (
"mime/multipart"
"net/url"
"github.com/spf13/cast"
)
type IRequest interface {
// url query
// e.g. foo.com?a=1&b=bar&c[]=bar
QueryAll(key string) url.Values
QueryIntWithDefault(key string, defval int) (int, bool)
QueryInt64WithDefault(key string, defval int64) (int64, bool)
QueryFloat32WithDefault(key string, defval float32) (float32, bool)
QueryFloat64WithDefault(key string, defval float64) (float64, bool)
QueryBoolWithDefault(key string, defval bool) (bool, bool)
QueryStringWithDefault(key string, defval string) (string, bool)
QueryStringSliceWithDefault(key string, defval []string) ([]string, bool)
// url params
// e.g. /book/:id
Param(key string) string
ParamIntWithDefault(key string, defval int) (int, bool)
ParamInt64WithDefault(key string, defval int64) (int64, bool)
ParamFloat32WithDefault(key string, defval float32) (float32, bool)
ParamFloat64WithDefault(key string, defval float64) (float64, bool)
ParamBoolWithDefault(key string, defval bool) (bool, bool)
ParamStringWithDefault(key string, defval string) (string, bool)
// form
FormAllWithDefault(key string) url.Values
FormIntWithDefault(key string, defval int) (int, bool)
FormInt64WithDefault(key string, defval int64) (int64, bool)
FormFloat32WithDefault(key string, defval float32) (float32, bool)
FormFloat64WithDefault(key string, defval float64) (float64, bool)
FormBoolWithDefault(key string, defval bool) (bool, bool)
FormStringWithDefault(key string, defval string) (string, bool)
FormStringSliceWithDefault(key string, defval []string) ([]string, bool)
FormFile(key string) (*multipart.FileHeader, error)
// JSON body
BindJSON(obj any) error
// XML body
BindXML(obj any) error
// RAW body
GetRawData() ([]byte, error)
// Basic informations
Uri() string
Method() string
Host() string
ClientIP() string
// Header
Headers() map[string][]string
Header(key string) (string, bool)
// Cookie
Cookies() map[string]string
Cookie(key string) (string, bool)
}
// {{{ url query
// QueryAll returns all queries in a request URL
func (ctx *Context) QueryAll() url.Values {
if ctx.Request != nil {
return map[string][]string(ctx.Request.URL.Query())
}
return url.Values{}
}
// QueryInt gets an int value from the query request
func (ctx *Context) QueryIntWithDefault(key string, defval int) (int, bool) {
params := ctx.QueryAll()
if vals, ok := params[key]; ok {
if len(vals) > 0 {
return cast.ToInt(vals[0]), true
}
}
return defval, false
}
func (ctx *Context) QueryInt64WithDefault(key string, defval int64) (int64, bool) {
params := ctx.QueryAll()
if vals, ok := params[key]; ok {
if len(vals) > 0 {
return cast.ToInt64(vals[0]), true
}
}
return defval, false
}
func (ctx *Context) QueryBoolWithDefault(key string, defval bool) (bool, bool) {
params := ctx.QueryAll()
if vals, ok := params[key]; ok {
if len(vals) > 0 {
return cast.ToBool(vals[0]), true
}
}
return defval, false
}
func (ctx *Context) QueryFloat32WithDefault(key string, defval float32) (float32, bool) {
params := ctx.QueryAll()
if vals, ok := params[key]; ok {
if len(vals) > 0 {
return cast.ToFloat32(vals[0]), true
}
}
return defval, false
}
func (ctx *Context) QueryFloat64WithDefault(key string, defval float64) (float64, bool) {
params := ctx.QueryAll()
if vals, ok := params[key]; ok {
if len(vals) > 0 {
return cast.ToFloat64(vals[0]), true
}
}
return defval, false
}
// QueryString gets a string value from the query request
func (ctx *Context) QueryStringWithDefault(key string, defval string) (string, bool) {
params := ctx.QueryAll()
if vals, ok := params[key]; ok {
if len(vals) > 0 {
return cast.ToString(vals[0]), true
}
}
return defval, false
}
// QueryArray gets an array of string values from the query request
func (ctx *Context) QueryStringSliceWithDefault(key string, defval []string) ([]string, bool) {
params := ctx.QueryAll()
if vals, ok := params[key]; ok {
return cast.ToStringSlice(vals[0]), true
}
return defval, false
}
// }}}
// {{{ url params
func (ctx *Context) ParamIntWithDefault(key string, def int) (int, bool) {
if val := ctx.Param(key); val != "" {
return cast.ToInt(val), true
}
return def, false
}
func (ctx *Context) ParamInt64WithDefault(key string, def int64) (int64, bool) {
if val := ctx.Param(key); val != "" {
return cast.ToInt64(val), true
}
return def, false
}
func (ctx *Context) ParamFloat64WithDefault(key string, def float64) (float64, bool) {
if val := ctx.Param(key); val != "" {
return cast.ToFloat64(val), true
}
return def, false
}
func (ctx *Context) ParamFloat32WithDefault(key string, def float32) (float32, bool) {
if val := ctx.Param(key); val != "" {
return cast.ToFloat32(val), true
}
return def, false
}
func (ctx *Context) ParamBoolWithDefault(key string, def bool) (bool, bool) {
if val := ctx.Param(key); val != "" {
return cast.ToBool(val), true
}
return def, false
}
func (ctx *Context) ParamStringWithDefault(key string, def string) (string, bool) {
if val := ctx.Param(key); val != "" {
return cast.ToString(val), true
}
return def, false
}
// }}}
// {{{ Post form
// FormAll gets everything from the submitted form
func (ctx *Context) FormAll() url.Values {
if ctx.Request != nil {
_ = ctx.Request.ParseForm()
return ctx.Request.PostForm
}
return url.Values{}
}
// FormInt gets an int value from the submitted form
func (ctx *Context) FormIntWithDefault(key string, defval int) (int, bool) {
params := ctx.FormAll()
if vals, ok := params[key]; ok {
if len(vals) > 0 {
return cast.ToInt(vals[0]), true
}
}
return defval, false
}
func (ctx *Context) FormInt64WithDefault(key string, defval int64) (int64, bool) {
params := ctx.FormAll()
if vals, ok := params[key]; ok {
if len(vals) > 0 {
return cast.ToInt64(vals[0]), true
}
}
return defval, false
}
func (ctx *Context) FormBoolWithDefault(key string, defval bool) (bool, bool) {
params := ctx.FormAll()
if vals, ok := params[key]; ok {
if len(vals) > 0 {
return cast.ToBool(vals[0]), true
}
}
return defval, false
}
func (ctx *Context) FormFloat32WithDefault(key string, defval float32) (float32, bool) {
params := ctx.FormAll()
if vals, ok := params[key]; ok {
if len(vals) > 0 {
return cast.ToFloat32(vals[0]), true
}
}
return defval, false
}
func (ctx *Context) FormFloat64WithDefault(key string, defval float64) (float64, bool) {
params := ctx.FormAll()
if vals, ok := params[key]; ok {
if len(vals) > 0 {
return cast.ToFloat64(vals[0]), true
}
}
return defval, false
}
func (ctx *Context) FormStringWithDefault(key string, defval string) (string, bool) {
params := ctx.FormAll()
if vals, ok := params[key]; ok {
if len(vals) > 0 {
return cast.ToString(vals[0]), true
}
}
return defval, false
}
func (ctx *Context) FormStringSliceWithDefault(key string, defval []string) ([]string, bool) {
params := ctx.FormAll()
if vals, ok := params[key]; ok {
return cast.ToStringSlice(vals[0]), true
}
return defval, false
}
// }}}
// {{{ Basic informations
func (ctx *Context) Uri() string {
return ctx.Request.RequestURI
}
func (ctx *Context) Method() string {
return ctx.Request.Method
}
func (ctx *Context) Host() string {
return ctx.Request.Host
}
// }}}
// {{{ Headers
// Header
func (ctx *Context) Headers() map[string][]string {
return ctx.Request.Header
}
// }}}
// {{{ Cookies
// Cookies gets cookie key-value pairs
func (ctx *Context) Cookies() map[string]string {
cookies := ctx.Request.Cookies()
ret := map[string]string{}
for _, c := range cookies {
ret[c.Name] = c.Value
}
return ret
}
// }}}

78
araneae_response.go Normal file
View File

@ -0,0 +1,78 @@
package gin
import (
"net/http"
)
type IResponse interface {
IJSON(status int, obj any) IResponse
IXML(status int, obj any) IResponse
IHTML(status int, filepath string, obj any) IResponse
IText(status int, format string, values ...any) IResponse
IRedirect(status int, path string) IResponse
ISetHeader(key string, val string) IResponse
ISetCookie(
key string,
val string,
maxAge int,
path, domain string,
secure, httpOnly bool,
) IResponse
ISetStatus(code int) IResponse
// set 200
ISetOKStatus() IResponse
}
func (ctx *Context) IJSON(status int, obj any) IResponse {
ctx.JSON(status, obj)
return ctx
}
func (ctx *Context) IXML(status int, obj any) IResponse {
ctx.XML(status, obj)
return ctx
}
func (ctx *Context) IHTML(status int, filepath string, obj any) IResponse {
ctx.HTML(status, filepath, obj)
return ctx
}
func (ctx *Context) IText(status int, format string, values ...any) IResponse {
ctx.String(status, format, values...)
return ctx
}
func (ctx *Context) IRedirect(status int, path string) IResponse {
ctx.Redirect(status, path)
return ctx
}
func (ctx *Context) ISetHeader(key string, val string) IResponse {
ctx.Header(key, val)
return ctx
}
func (ctx *Context) ISetCookie(
key string,
val string,
maxAge int,
path, domain string,
secure, httpOnly bool,
) IResponse {
ctx.SetCookie(key, val, maxAge, path, domain, secure, httpOnly)
return ctx
}
func (ctx *Context) ISetStatus(code int) IResponse {
ctx.Status(code)
return ctx
}
// set 200
func (ctx *Context) ISetOKStatus() IResponse {
ctx.Status(http.StatusOK)
return ctx
}

2
go.mod
View File

@ -11,6 +11,7 @@ require (
github.com/mattn/go-isatty v0.0.20 github.com/mattn/go-isatty v0.0.20
github.com/pelletier/go-toml/v2 v2.2.2 github.com/pelletier/go-toml/v2 v2.2.2
github.com/quic-go/quic-go v0.43.1 github.com/quic-go/quic-go v0.43.1
github.com/spf13/cast v1.7.0
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.9.0
github.com/ugorji/go/codec v1.2.12 github.com/ugorji/go/codec v1.2.12
golang.org/x/net v0.27.0 golang.org/x/net v0.27.0
@ -29,7 +30,6 @@ require (
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/leodido/go-urn v1.4.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect

6
go.sum
View File

@ -9,10 +9,11 @@ github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
@ -62,7 +63,6 @@ github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
@ -71,6 +71,8 @@ github.com/quic-go/quic-go v0.43.1 h1:fLiMNfQVe9q2JvSsiXo4fXOEguXHGGl9+6gLp4RPeZ
github.com/quic-go/quic-go v0.43.1/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M= github.com/quic-go/quic-go v0.43.1/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=