如何将gin gonic中的原始数据传递给gRPC微服务?

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

How can I pass the origin from gin gonic to a gRPC microservice

问题

我正在编写一个支持多个来源的微服务(这些来源定义了要连接的数据库)。为了做到这一点,我需要获取来源信息。使用gin作为服务器负责验证来源,而rpc微服务不验证任何内容。我唯一遗漏的是如何将这些元数据传递给上下文中的rpc服务。

我尽量简化了这个想法,实际情况要复杂得多,并且有多个值要传递。将所有这些内容传递给所有函数是不可行的,因为这会产生太多的开销。

Gin服务器

  1. func OriginMiddleware() gin.HandlerFunc {
  2. return func(context *gin.Context) {
  3. origin := context.GetHeader("origin")
  4. // 将origin添加到上下文中
  5. context.Next()
  6. }
  7. }
  8. func main(){
  9. ... // 设置grpc等
  10. r.Use(OriginMiddleware())
  11. r.POST("/login", User.Login)
  12. r.GET("/getUser", User.Get)
  13. ... // 其他许多端点
  14. r.Run("localhost:8080")
  15. }

微服务

  1. func OriginInterceptor() grpc.UnaryServerInterceptor {
  2. return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
  3. origin := ctx.Value("origin")
  4. fmt.Println(origin)
  5. ... // 获取或创建数据库连接等操作
  6. return handler(ctx, req)
  7. }
  8. }
  9. func main() {
  10. ... // 设置
  11. s := grpc.NewServer(grpc.UnaryInterceptor(MongoInterceptor()))
  12. UserPB.RegisterUserServiceServer(s, &server{})
  13. ... // 启动服务
  14. }

我尝试过的方法

  • 重写gin上下文似乎是不可能的
  • 使用.Set只在"gin"服务器内部有效,但在发送到grpc时所有值都丢失了
英文:

I'm writing a microservice that supports multiple origins (which then define what database to connect to). In order to do that I need for example the origin. The server with gin is responsible to validate the origin, the rpc microservice does not validate anything. The only point that I am missing is how to pass this metadata to the rpc service inside the context.

I simplified the idea as much as I could, the real case is way more complex, and there is more than 1 value to pass. Passing all those things to all functions is out of discussion, as it would generate way too much overhead

Gin server

  1. func OriginMiddleware() gin.HandlerFunc {
  2. return func(context *gin.Context) {
  3. origin := context.GetHeader("origin")
  4. // add origin to the context
  5. context.Next()
  6. }
  7. }
  8. func main(){
  9. ... // setup grpc etc
  10. r.Use(OriginMiddleware())
  11. r.POST("/login", User.Login)
  12. r.GET("/getUser", User.Get)
  13. ... // many other endpoints
  14. r.Run("localhost:8080")
  15. }

Microservice

  1. func OriginInterceptor() grpc.UnaryServerInterceptor {
  2. return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
  3. origin := ctx.Value("origin")
  4. fmt.Println(origin)
  5. ... // get or create db connection whatsoever
  6. return handler(ctx, req)
  7. }
  8. }
  9. func main() {
  10. ... // setup
  11. s := grpc.NewServer(grpc.UnaryInterceptor(MongoInterceptor()))
  12. UserPB.RegisterUserServiceServer(s, &server{})
  13. ... // serve
  14. }

What I've been trying

  • Overwriting the gin context doesn't seem possible
  • Using .Set works only as long as it's inside the "gin" server, but all values are lost when sent to grpc

答案1

得分: 1

我找到了一个可行的解决方案,但并不是最干净的。欢迎提出改进和批评意见!

  1. func ToGrpcContext(ctx *gin.Context) context.Context {
  2. res := make(map[string]string)
  3. for key, value := range ctx.Keys {
  4. switch v := value.(type) {
  5. case string:
  6. res[key] = v
  7. }
  8. }
  9. return metadata.NewOutgoingContext(ctx, metadata.New(res))
  10. }

每次调用任何grpc函数时,我都会使用这个辅助函数包装上下文,例如:

  1. user, err := UserPB.GetUser(ToGrpcContext(ctx), &UserPB.GetUserInput{...})
英文:

I found a solution that works, but it's not the cleanest. Improvements and critics are well accepted!

  1. func ToGrpcContext(ctx *gin.Context) context.Context {
  2. res := make(map[string]string)
  3. for key, value := range ctx.Keys {
  4. switch v := value.(type) {
  5. case string:
  6. res[key] = v
  7. }
  8. }
  9. return metadata.NewOutgoingContext(ctx, metadata.New(res))
  10. }

Each time I call any grpc function, I wrap the context with this helper function, like:

  1. user, err := UserPB.GetUser(ToGrpcContext(ctx), &UserPB.GetUserInput{...})

huangapple
  • 本文由 发表于 2022年2月19日 18:50:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/71184277.html
匿名

发表评论

匿名网友

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

确定