【问题标题】:gRPC stream interceptor not passing context to request methodgRPC 流拦截器未将上下文传递给请求方法
【发布时间】: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() 方法。尝试实现覆盖它的方法。

标签: go grpc


【解决方案1】:

如果它对任何人有帮助,我们已经打开了我们的一个存储库来证明这一点。

https://github.com/drud/api-common/blob/main/interceptors/state.go#L207

与@Bluskript impl 非常相似,但是我没有遇到上述相同的问题。我相信这可能来自返回类型 grpc.StreamServerInterceptor 以及我使用上下文获取器的位置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-25
    • 2017-12-09
    • 1970-01-01
    • 2019-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多