如何将 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
}
我一直在尝试的
- 覆盖 gin 上下文似乎不可能
- 使用
.Set
只有在“gin”服务器内时才有效,但发送到 grpc 时所有值都会丢失
我找到了一个可行的解决方案,但它不是最干净的。改进和批评被广泛接受!
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{...})
我正在编写一个支持多个来源的微服务(然后定义要连接到的数据库)。为此,我需要例如原点。带有 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
}
我一直在尝试的
- 覆盖 gin 上下文似乎不可能
- 使用
.Set
只有在“gin”服务器内时才有效,但发送到 grpc 时所有值都会丢失
我找到了一个可行的解决方案,但它不是最干净的。改进和批评被广泛接受!
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{...})