Interceptorで認証情報などの値をコンテキストに入れて使いたいときがあります。
Unary RPCだと、第一引数で受け取ったコンテキストをそのまま使えばいいですが、Stream RPCの場合は一工夫必要だったのでメモしておきます。
ContextとServerStreamをEmbedded fieldとして持つStructを定義して、それをhandlerに渡します。
実際のStreamの処理でContext()を呼び出せば、値を入れたコンテキストを取り出すことが出来ます。
func myStreamServerInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
ctx := context.WithValue(ss.Context(), "key", "value")
return handler(srv, &serverStreamWrapper{
ServerStream: ss,
ctx: ctx,
})
}
}
type serverStreamWrapper struct {
grpc.ServerStream
ctx context.Context
}
func (s *serverStreamWrapper) Context() context.Context { return s.ctx }