无法获取地图的键,即使 gin 的上下文结构将标题作为地图



我无法从Gin的上下文中获得所有密钥。Header (Golang的gin-gonic http/rest框架)字段,尽管Header被定义为Map类型Header Map [string][]string"(报头来自nethttp报头。Go,请求是来自nethhtp请求。go, Context来自Gin-gonic的包),令人惊讶的是,即使在编译/构建时,Visual Studio代码也不允许我调用/使用"MapKeys()"。

  1. 我需要复制所有的HTTP头到记录器,这样当我记录任何消息时,我可以把相应的请求头。
  2. 我还需要将所有HTTP头从HTTP传递到gRPC调用,以实现端到端调用可追溯性需求。
func (l *Logger) InfoCtx(ctx *gin.Context, md metadata.MD) *zerolog.Event {
headerName := "X-Request-Id" // Read all the headers from the ENV file
// mapping := make(map[string]string)
// mapping[headerName] = ctx.Request.Header[headerName][0]
event := l.Logger.Info()

// ctx.Request.Header ==> Even though this is a "map" type, 
// which is known at the compilation time itself, 
// it doesn't let me use any map functions.
if ctx != nil && len(ctx.Request.Header[headerName]) > 0 {
event = event.Str(headerName, ctx.Request.Header[headerName][0])
} else if md != nil {
// some other gRPC metadata context handling (not relevant for this question)

}
return event
}

你能帮帮忙吗?

头对象

请求对象使用报头字段

显示标头为映射类型

我可能误解了你的问题,但我能够从Gin的上下文中枚举请求头的映射:

go.mod:

module github.com/OWNER/stackoverflow/69315290
go 1.16
require github.com/gin-gonic/gin v1.7.4

main.go:

package main
import (
"log"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
for k, v := range c.Request.Header {
log.Printf("%s: %v", k, v)
}
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run()
}

:

curl --header "dog: freddie" localhost:8080/ping

收益率:

{"message":"pong"}

:

2021/09/25 10:41:05 User-Agent: [curl/7.68.0]
2021/09/25 10:41:05 Accept: [*/*]
2021/09/25 10:41:05 Dog: [freddie]
[GIN] 2021/09/25 - 10:41:05 | 200 |     408.631µs |       127.0.0.1 | GET      "/ping"

另一个对我有效的方法是,

  1. 我创建了一个struct有"HttpHeadersMap map[string][]string"在
type CommonContext struct {
HttpHeadersMap map[string][]string
RequestContext context.Context
GrpcMDHeadersMap map[string][]string
}
  1. 指定的Gin's "ctx.Request.Header"HttpHeadersMap映射[string][]string">
func GetCommonCtx(ctx *gin.Context, md metadata.MD) CommonContext {
var commonContext CommonContext
if ctx != nil {
// event = event.Str(headerName, ctx.Request.Header[headerName][0])
commonContext = CommonContext{ // don't return address, use valye type
HttpHeadersMap: ctx.Request.Header,
RequestContext: ctx.Request.Context(),
}
}
...
}
  • 然后在"gRPC拦截器(只是显示示例用例)",我可以使用"HttpHeadersMap"headersMapVal.MapKeys()"来迭代Map键。

    func clientInterceptor(
    ctx context.Context,
    method string,
    req interface{},
    reply interface{},
    cc *grpc.ClientConn,
    invoker grpc.UnaryInvoker,
    opts ...grpc.CallOption,
    ) error {
    start := time.Now()
    commonCtx := commonContext.GetCommonCtx(nil, metadata.MD{})
    if callOpt, ok := opts[0].(CustomDataCallOption); ok {
    headersMapVal := reflect.ValueOf(callOpt).FieldByName("HeadersMap")
    newMap := make(map[string]string)
    // allKeysMap := make(map[string]string)
    for _, key := range headersMapVal.MapKeys() {
    // fmt.Printf("headersMapVal.MapKeys(), e %v", e)
    // c_key := e.Convert(headersMapValueIndirectStr.Type().Key())
    keyValue := headersMapVal.MapIndex(key)
    ...
    ...
    }
    

    最新更新