【发布时间】:2020-08-21 07:33:33
【问题描述】:
我有以下 gRPC 拦截器在服务器端运行,它包装了一个服务器流并将其传递给下一个处理程序:
// HarmonyContext contains a custom context for passing data from middleware to handlers
type HarmonyContext struct {
context.Context
Request interface{}
UserID uint64
Limiter *rate.Limiter
}
type IHarmonyWrappedServerStream interface {
GetWrappedContext() HarmonyContext
}
type HarmonyWrappedServerStream struct {
grpc.ServerStream
WrappedContext HarmonyContext
}
func (ss HarmonyWrappedServerStream) GetWrappedContext() HarmonyContext {
return ss.WrappedContext
}
func (m Middlewares) HarmonyContextInterceptorStream(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
wrapped := WrapServerStream(ss)
return handler(srv, wrapped)
}
func WrapServerStream(stream grpc.ServerStream) HarmonyWrappedServerStream {
if existing, ok := stream.(HarmonyWrappedServerStream); ok {
return existing
}
return HarmonyWrappedServerStream{ServerStream: stream, WrappedContext: HarmonyContext{
Context: stream.Context(),
}}
}
在处理程序本身中,我有以下代码:
func (v1 *V1) StreamGuildEvents(r *corev1.StreamGuildEventsRequest, s corev1.CoreService_StreamGuildEventsServer) error {
wrappedStream := s.(middleware.IHarmonyWrappedServerStream)
println(wrappedStream)
return nil
}
但是,我在发送流式传输请求时收到以下运行时错误:
interface conversion: *corev1.coreServiceStreamGuildEventsServer is not middleware.IHarmonyWrappedServerStream: missing method GetWrappedContext
实际上,handler 中的 ServerStream 与拦截器中的 ServerStream 完全不同。有没有办法让拦截器正确传递自定义的ServerStream?
【问题讨论】:
-
服务处理器不需要进行类型断言。拦截器对处理程序应该是透明的。另请参阅此处的拦截器示例:github.com/grpc/grpc-go/tree/master/examples/features/…
-
感谢您的评论。我想做出断言的原因是能够在流拦截器和处理程序本身之间传递上下文/数据。有什么办法吗?
-
覆盖pkg.go.dev/google.golang.org/grpc?tab=doc#ClientStream 的方法将是传递/修改数据的好方法。 context() 可用于包装父上下文。
-
正如我为问题提供的代码中所见,我已经这样做了。我将 ServerStream 结构包装在一个拦截器中,并覆盖了上下文。但是在测试的时候,handler的stream参数好像没有从拦截器传过来。
-
提供的代码 sn-p 仅嵌入
grpc.ServerStream,但不会覆盖Context()方法。尝试实现覆盖它的方法。