1
需求: 想基于路由中间件开发一个公共拦截器,但是拦截器内部需要查询缓存以及微服务接口,由于gozero框架不支持将ServiceContext参数传递给中间件,所以无法实现
建议: 可以支持ServiceContext参数传递给路由中间件,这样路由中间件的功能就不受限制了
需求: 想基于路由中间件开发一个公共拦截器,但是拦截器内部需要查询缓存以及微服务接口,由于gozero框架不支持将ServiceContext参数传递给中间件,所以无法实现
建议: 可以支持ServiceContext参数传递给路由中间件,这样路由中间件的功能就不受限制了
局部的能传进去的
你意思是使用全局中间件吗,我试了能传进去,但是运行时panic了,代码如下
func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)
ctx := svc.NewServiceContext(c)
server := rest.MustNewServer(c.RestConf)
defer server.Stop()
server.Use(func(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var myctx context.Context
resp, _ := ctx.Verify.Ping(myctx, &verify.Request{
Ping: "pingtest",
})
w.WriteHeader(200)
w.Write([]byte(resp.Pong))
next(w, r)
}
})
handler.RegisterHandlers(server, ctx)
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
server.Start()
}
不是全局的,是局部的,我是这样用的,我之前做权限拦截的时候 ,在登录的时候 用redis缓存起来,然后在局部中间件拿redis里面的值出来对比拦截的
func NewServiceContext(c config.Config) *ServiceContext {
newRedis := redis.NewRedis(c.Redis.Address, redis.NodeType)
return &ServiceContext{
Config: c,
CheckUrl: middleware.NewCheckUrlMiddleware(newRedis).Handle,
Redis: newRedis,
}
}
middleware代码如下
func (m *CheckUrlMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
//判断请求header中是否携带了x-user-id
userId := r.Context().Value("userId").(json.Number).String()
if userId == "" {
logx.Errorf("缺少必要参数x-user-id")
httpx.Error(w, errorx.NewDefaultError("缺少必要参数x-user-id"))
return
}
//获取用户能访问的url
urls, err := m.Redis.Get(userId)
if err != nil {
logx.Errorf("用户:%s,获取redis连接异常", userId)
httpx.Error(w, errorx.NewDefaultError(fmt.Sprintf("用户:%s,获取redis连接异常", userId)))
return
}
if len(strings.TrimSpace(urls)) == 0 {
logx.Errorf("用户userId: %s,还没有登录", userId)
httpx.Error(w, errorx.NewDefaultError(fmt.Sprintf("用户userId: %s,还没有登录,请先登录", userId)))
return
}
backUrls := strings.Split(urls, ",")
b := false
for _, url := range backUrls {
if url == r.RequestURI {
b = true
break
}
}
if b || r.RequestURI == "/api/sys/user/currentUser" || r.RequestURI == "/api/sys/user/selectAllData" || r.RequestURI == "/api/sys/role/queryMenuByRoleId" {
logx.Infof("用户userId: %s,访问: %s路径", userId, r.RequestURI)
next(w, r)
} else {
logx.Errorf("用户userId: %s,没有访问: %s路径的权限", userId, r.RequestURI)
httpx.Error(w, errorx.NewDefaultError(fmt.Sprintf("用户userId: %s,没有访问: %s,路径的的权限,请联系管理员", userId, r.RequestURI)))
return
}
}
}
理解了,感谢大佬!