需求场景

最近的开发过程中遇到一个场景,用go-zero开发的api服务中,除了login api外其他的api需要进行登录的认证(很普通的场景)。但由于整个后端架构是微服务模式,提供用户及登录验证的是另一个grpc服务。所以出现了需要在api的中间件中调用 用户rpc服务的问题。查了官网没有得到明确的答案。故将研究过程及最后方案记录如此。供后人享用。


了解api中间件

如下代码为使用go-zero自动生成的初始中间件代码

package middleware

import "net/http"

type AuthMiddleware struct {
}

func NewAuthMiddleware() *AuthMiddleware {
        return &AuthMiddleware{}
}

func (m *AuthMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        // TODO generate middleware implement function, delete after code implementation

        // Passthrough to next handler if need
        next(w, r)
    }
}

根据官网提示,使用中间件需要在ServiceContext 中注册中间件,示例代码如下

type ServiceContext struct {
	Config         config.Config  #配置文件
	UserRpc        user.User # 用户grpc服务
	AuthMiddleware rest.Middleware # 本次示例中间件
}

func NewServiceContext(c config.Config) *ServiceContext {
	return &ServiceContext{
		Config:         c,
		AuthMiddleware: middleware.NewAuthMiddleware().Handle,  # 初始注册中间件的方法
		UserRpc:        user.NewUser(zrpc.MustNewClient(c.UserRpc)),
	}
}
改造中间件

官网中虽然也提到了《在中间件中调用其他服务》 的章节,但并没有提供详细的demo案例。新萌小白可能不太好理解。这里大概讲解一下(自我领悟),如果需要在中间件中调用其他服务,需要在注册中间件的时候,将被调用服务的句柄(不知道怎么描述这个词暂时用句柄代替吧) 以参数形式传递到中间件里。(举一反三啊 如果想在中间件中调用配置文件参数亦是如此)。所以需要在中间件的初始struct中 先设置好被引入的组件类型。在NewAuthMiddleware()方法中进行初始化。

示例代码如下:(请参照上方初始代码比较观看)

type AuthMiddleware struct {
	Config  config.Config ## 增加了配置文件
	UserRpc user.User ## 增加了用户rpc服务的句柄
}
// 增加了入参c r 分别是配置文件句柄和用户rpc服务句柄
func NewAuthMiddleware(c config.Config, r user.User) *AuthMiddleware {
	return &AuthMiddleware{
		Config:  c, //这里进行初始化
		UserRpc: r,
	}
}

func (m *AuthMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		Authorization := r.Header.Get("Authorization")
       
        // 上方注册好之后 在这里就可以调用rpc服务了
		tokenData, err := m.UserRpc.CheckLogin(r.Context(), &users.CheckLoginRequest{
			Token: Authorization,
		})
        
		if err != nil {
			httpx.ErrorCtx(r.Context(), w, "没有提供token")
			return
		}
		next(w, r)
	}
}

如上 ,改造完成后即可在中间件中调用rpc服务了

go-zero 如何在api的中间件中调用rpc服务_go-zero


阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: go