英文:
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
。
有什么最好的方法来解决这个问题?
英文:
I have a UnaryServerInterceptor
that receives a req
Interface{}
. This req
could be any one of my messages, but in this case all my messages have a metadata
child message in common.
Protobuf definitions (sample)
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) {}
}
Interceptor
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)
}
}
I need to access the properties of the message's metadata
in my interceptor. The problem is that I don't know which message it is, so I can't just cast it. I have several different messages but they all have metadata
in common.
What's the best way to go about this?
答案1
得分: 4
protoc
生成的代码应该为两种类型都生成了一个名为GetMetadata
的方法。你可以使用类型断言(详见Go之旅)来检查传入的消息是否实现了一个接口,然后调用该方法来获取元数据。
type HasMetadata interface {
GetMetadata() *ClientMeta
}
在处理消息的函数中,可以这样做:
if m, ok := req.(HasMetadata); ok {
return m.GetMetadata()
}
英文:
The protoc
generation should have produced a method called GetMetadata
for both types. You can check if the incoming message implements an interface using a type assertion (see the tour of go for more details), then call that method to get the metadata.
type HasMetadata interface {
GetMetadata() *ClientMeta
}
In the function that handles the message, do something like this
if m, ok := req.(HasMetadata); ok {
return m.GetMetadata()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论