【问题标题】:Cast request in gRPC interceptor to relevant protobuf message将 gRPC 拦截器中的请求转换为相关的 protobuf 消息
【发布时间】:2021-06-04 16:14:52
【问题描述】:

我有一个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 的共同点。

最好的方法是什么?

【问题讨论】:

  • 旁注:Go 没有 casts,但有类型转换、类型切换和类型断言。 T(x)(其中 T 是类型,x 是值)是类型转换; x.(T) 是一个类型断言; switch x.(type) { ... } 是一个类型开关。这个主题有一些小的变化。 gRPC 编译器进行了设置,以便您可以合理干净地使用这些(如在已经接受的答案中)。

标签: go protocol-buffers grpc


【解决方案1】:

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

type HasMetadata interface {
    GetMetadata() *ClientMeta
}

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

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

【讨论】:

    猜你喜欢
    • 2018-05-31
    • 2021-09-10
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 2019-07-15
    • 2018-08-11
    • 1970-01-01
    • 2019-11-24
    相关资源
    最近更新 更多