如何在服务器端读取grpc中的元数据?(golang例子)

San*_*ket 6 go grpc

如何在grpc中读取服务器端的元数据(作为标题传递)?golang的任何一个例子?

我写的是这样的:

// this should be passed from the client side as a context and needs to accessed on server side to read the metadata
var headers = metadata.New(map[string]string{"authorization": "", "space":  "", "org": "", "limit": "", "offset": ""})
Run Code Online (Sandbox Code Playgroud)

我想将授权令牌传递给我的验证函数以验证收到的令牌.

func validate_token(ctx context.Context, md *metadata.MD) (context.Context, error){
    token := headers["authorization"]
}
Run Code Online (Sandbox Code Playgroud)

Zac*_*her 19

在调用服务器之前,必须将元数据插入客户端的上下文中.

对于一元RPC,客户端看起来像:

conn, _ := grpc.Dial(address, opts...)
client := NewMyClient(conn) // generated from your proto with the grpc protoc option

header := metadata.New(map[string]string{"authorization": "", "space":  "", "org": "", "limit": "", "offset": ""})
// this is the critical step that includes your headers
ctx := metadata.NewContext(context.Background(), header)

request := // construct a request for your service
response, err := client.MyMethod(ctx, request)
Run Code Online (Sandbox Code Playgroud)

对于流,它看起来几乎相同:

conn, _ := grpc.Dial(address, opts...)
client := NewMyClient(conn) // generated from your proto with the grpc protoc option

header := metadata.New(map[string]string{"authorization": "", "space":  "", "org": "", "limit": "", "offset": ""})
// this is the critical step that includes your headers
ctx := metadata.NewContext(context.Background(), header)
stream, err := client.MyMethodStream(ctx)

for {
    request :=  // construct a request for your service
    err := stream.Send(request)
    response := new(Response)
    err = stream.RecvMsg(response)
}
Run Code Online (Sandbox Code Playgroud)

在服务器端为一元RPC:

func (s myServer) MyMethod(context.Context, *Request) (*Response, error) {
    headers, ok := metadata.FromContext(ctx)
    token := headers["authorization"]
}
Run Code Online (Sandbox Code Playgroud)

并为流式RPC:

func (s myServer) MyMethodStream(stream MyMethod_MyServiceStreamServer) error {
    headers, ok := metadata.FromContext(stream.Context())
    token := headers["authorization"]
    for {
        request := new(Request)
        err := stream.RecvMsg(request)
        // do work
        err := stream.SendMsg(response)
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,对于流,只有三次可以发送标头:在用于打开初始流的上下文中,通过grpc.SendHeadergrpc.SetTrailer.无法在流中的任意消息上设置标头.对于每个消息发送一元RPC头,可以在初始上下文中设置grpc.SendHeader和grpc.SetHeader以及grpc.SetTrailer.

  • 在更高的gRPC版本中,它是`metadata.FromIncomingContext`。 (2认同)
  • 传入和传出上下文有什么区别? (2认同)

Joe*_*e B 8

原始答案是正确的,但阅读标题有点过时了

import "google.golang.org/grpc/metadata"

func (s myServer) MyMethod(ctx context.Context, *Request) (*Response, error) {
  var values []string
  var token string

  md, ok := metadata.FromIncomingContext(ctx)
  if ok {
    values = md.Get("authorization")
  }

  if len(values) > 0 {
    token = values[0]
  }

  // do something with token
}
Run Code Online (Sandbox Code Playgroud)