如何将 gin gonic 的来源传递给 gRPC 微服务

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

我正在编写一个支持多个来源的微服务(然后定义要连接到的数据库)。为此,我需要例如原点。带有 gin 的服务器负责验证来源,rpc 微服务不验证任何内容。我唯一缺少的一点是如何将此元数据传递给上下文中的 rpc 服务。

我尽可能地简化了这个想法,实际情况要复杂得多,而且要传递的值不止 1 个。将所有这些东西传递给所有函数不在讨论之列,因为它会产生太多开销

杜松子酒服务器

func OriginMiddleware() gin.HandlerFunc {
    return func(context *gin.Context) {

        origin := context.GetHeader("origin")
        
        // add origin to the context

        context.Next()
    }
}

func main(){
    
    ...  // setup grpc etc

    
    r.Use(OriginMiddleware())

    r.POST("/login", User.Login)
    r.GET("/getUser", User.Get)

    ... // many other endpoints

    r.Run("localhost:8080")
}

微服务


func OriginInterceptor() grpc.UnaryServerInterceptor {
    return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
        origin := ctx.Value("origin")
        fmt.Println(origin)
    
        ... // get or create db connection whatsoever
 
        return handler(ctx, req)
    }
}

func main() {
    ... // setup
    
    s := grpc.NewServer(grpc.UnaryInterceptor(MongoInterceptor()))
    
    UserPB.RegisterUserServiceServer(s, &server{})

    ... // serve
}

我一直在尝试的

我找到了一个可行的解决方案,但它不是最干净的。改进和批评被广泛接受!

func ToGrpcContext(ctx *gin.Context) context.Context {
    res := make(map[string]string)
    for key, value := range ctx.Keys {
        switch v := value.(type) {
        case string:
            res[key] = v
        }
    }
    return metadata.NewOutgoingContext(ctx, metadata.New(res))
}

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

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