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

huangapple go评论82阅读模式
英文:

Cast request in gRPC interceptor to relevant protobuf message

问题

我有一个UnaryServerInterceptor,它接收一个reqInterface{}。这个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()
}

huangapple
  • 本文由 发表于 2021年6月5日 00:14:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/67840654.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定