Go-gRPC过滤器中元数据获取与grpcgateway前缀元数据设置问题
关于gRPC-Gateway元数据设置的问题解答
问题场景
配置gRPC链式Unary拦截器时,最初编写了如下代码:
func GetChainUnaryServerInterceptor() grpc.UnaryServerInterceptor { return grpc_middleware.ChainUnaryServer( grpc_auth.UnaryServerInterceptor(auth.CookieAuth), parseSessionToUidFilter, ) } func parseSessionToUidFilter(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { ctx = metadata.NewOutgoingContext(ctx, metadata.Pairs("uid", "123")) return handler(ctx, req) }
服务端Echo方法尝试从入站上下文获取元数据:
func (s *server) Echo(ctx context.Context, req *pb.EchoRequest) (resp *pb.EchoReply, err error) { md, _ := metadata.FromIncomingContext(ctx) fmt.Println(md) u := md.Get("uid")[0] username := u if username == "" { username = "whoever you are" } return &pb.EchoReply{Echo: "Hello, " + username}, nil }
调试发现uid元数据未被正确识别,后续得知应使用NewIncomingContext设置元数据,现咨询:如何设置带有grpcgateway-*前缀(如grpcgateway-uid)的元数据,是否需要在启动gRPC-Gateway时重写incomingHeaderMatcher函数?
解答
1. 正确设置带grpcgateway-*前缀的元数据
在拦截器中,需要使用metadata.NewIncomingContext修改入站元数据(而非出站元数据),直接添加带前缀的键名即可:
func parseSessionToUidFilter(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { // 先获取当前上下文的入站元数据,若无则初始化空元数据 md, ok := metadata.FromIncomingContext(ctx) if !ok { md = metadata.New(nil) } // 添加带grpcgateway-前缀的元数据 md.Set("grpcgateway-uid", "123") // 将更新后的元数据绑定回上下文 ctx = metadata.NewIncomingContext(ctx, md) return handler(ctx, req) }
之后在服务端Echo方法中,即可通过md.Get("grpcgateway-uid")获取对应值:
func (s *server) Echo(ctx context.Context, req *pb.EchoRequest) (resp *pb.EchoReply, err error) { md, _ := metadata.FromIncomingContext(ctx) u := "" if vals := md.Get("grpcgateway-uid"); len(vals) > 0 { u = vals[0] } username := u if username == "" { username = "whoever you are" } return &pb.EchoReply{Echo: "Hello, " + username}, nil }
2. 是否需要重写incomingHeaderMatcher?
不需要。
incomingHeaderMatcher的作用是gRPC-Gateway在将HTTP请求转换为gRPC请求时,筛选并映射HTTP请求头到gRPC元数据中。- 你的场景是在gRPC服务端拦截器里主动生成并设置元数据,完全不涉及HTTP请求头的映射逻辑,因此无需修改该函数。只有当你需要让Gateway将特定HTTP请求头(如自定义的
X-UID)映射为grpcgateway-uid元数据时,才需要重写这个函数。
内容的提问来源于stack exchange,提问作者jay cole
相关产品推荐
相关产品推荐

