[ go-zero使用api的全局中间件 ]


go-zero中api服务使用全局拦截器

1.中间件

package apiserver

import (
    "context"
    "fmt"
    "go-weixin/app/usercenter/userrpc/pb/proto/usercenter"
    "go-weixin/app/usercenter/userrpc/userrpcclient"
    "go-weixin/common/ctxdata"
    "net/http"
    "regexp"
    "strconv"
    "time"

    mapset "github.com/deckarep/golang-set/v2"
    "github.com/zeromicro/go-zero/rest/httpx"
    "github.com/zeromicro/x/errors"
    "google.golang.org/grpc"
)

type ApiAuthMiddleware struct {
    UserRpc userrpcclient.UserCenter
}

func NewApiMiddleware(userRpc userrpcclient.UserCenter) *ApiAuthMiddleware {
    return &ApiAuthMiddleware{
        UserRpc: userRpc,
    }
}

func (m *ApiAuthMiddleware) AuthMiddleware(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        url := r.URL.Path
        uid := ctxdata.GetUidFromCtx(r.Context())
        if (url != "/user/login") && (url != "/user/register") && (uid != 1) {
            ctx, cannFunc := context.WithTimeout(context.Background(), 5*time.Second)
            defer cannFunc()
            res, err := m.UserRpc.UserGetPower(ctx, &usercenter.UserGetPowerReq{
                Id: uid,
            })
            if err != nil {
                httpx.ErrorCtx(r.Context(), w, errors.New(400, err.Error()))
                return
            }
            powerList := mapset.NewSet[string]()
            if len(res.PowerList) > 0 {
                for _, power := range res.PowerList {
                    powerList.Add(power.Url)
                }
            }
            fmt.Println(powerList)
            fmt.Printf("auth请求路径: %s \n", url)
            if !powerList.Contains(url) {
                httpx.ErrorCtx(r.Context(), w, errors.New(404, "没有权限请求此路径"))
                return
            }
        }
        next(w, r)
    }
}

// rpc-client客户端拦截器
func ClientRpcMiddleware(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
    err := invoker(ctx, method, req, reply, cc, opts...)
    if err != nil {
        errStr := err.Error()
        reg := regexp.MustCompile(`code = Code\((?P<code>\d+)\) desc = (?P<msg>.*)`)
        res := reg.FindAllStringSubmatch(errStr, 1)
        for _, match := range res {
            codeStr := match[reg.SubexpIndex("code")]
            msg := match[reg.SubexpIndex("msg")]
            code, e := strconv.Atoi(codeStr)
            if e != nil {
                code = 7000
            }
            err = errors.New(code, msg)
        }
        return err
    }
    return nil
}

2. 注册路由

router.go

func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
    server.Use(serverCtx.ApiMDLE.AuthMiddleware)
    ...
    ...
}