将 gRPC 拦截器中的请求转换为相关的 protobuf 消息

Cast request in gRPC interceptor to relevant protobuf message

我有一个 UnaryServerInterceptor 接收 req Interface{}。此 req 可以是我的任何一条消息,但在这种情况下,我的所有消息都有一个共同的 metadata 子消息。

Protobuf 定义(示例)

message ClientMeta {
    string info = 1;
}

message PingRequest {
    ClientMeta metadata = 1;
}

message OtherRequest {
    ClientMeta metadata = 1;
}

service Blah {
    rpc Ping (PingRequest) returns (PingResponse) {}
    rpc Other (OtherRequest) returns (OtherResponses) {}
}

拦截器

func (i *authInterceptor) unary() grpc.UnaryServerInterceptor {
    return func(
        ctx context.Context,
        req interface{},
        info *grpc.UnaryServerInfo,
        handler grpc.UnaryHandler,
    ) (interface{}, error) {
        log.Info().Msgf("interceptor: %s", info.FullMethod)
    }
}

我需要在我的拦截器中访问消息 metadata 的属性。问题是我不知道它是哪条消息,所以我不能直接投射它。我有几条不同的消息,但它们都有 metadata 的共同点。

解决此问题的最佳方法是什么?

protoc 一代应该为这两种类型产生了一种名为 GetMetadata 的方法。您可以使用 类型断言 检查传入消息是否实现了接口(有关详细信息,请参阅 tour of go),然后调用该方法来获取元数据。

type HasMetadata interface {
    GetMetadata() *ClientMeta
}

在处理消息的函数中,做这样的事情

if m, ok := req.(HasMetadata); ok {
    return m.GetMetadata()
}