从零实现gin day05 中间件(日志,鉴权等实现)

68 阅读2分钟

前言

上一章我们实现了路由分组的逻辑.我们这一章根据路由分组来丰富框架的功能.一般来说鉴权,日志这种通用的功能我们可以抽象成中间件加在框架之中.例如针对/admin/index /admin/*下的所有路径判断是否已经登录,针对所有的路由加操作日志.

代码实现

RouterGroup结构体修改

  • middleware []HandleFunc 中间件
  • handlers 让Context存储handlers中间件组,用于调用
  • index 判断当前需要执行的中间件HandleFunc
type RouterGroup struct {  
    prefix string  
    middleware []HandleFunc  
    engine *Engine  
    parent *RouterGroup  
}

type Context struct {  
    Writer http.ResponseWriter  
    Req *http.Request  
    Params map[string]string  
    Method string  
    Path string  
    StatusCode int  
    handlers []HandleFunc  
    index int  当前执行的handler
}

RouterGroup,Router,Context函数修改

  • Use添加handler进中间件中
  • 找到下一个中间件的HandleFunc
  • 因为这里是index++开始,所以index要初始化为0
  • Handle将路由的handler绑定到Context中,通过Next去调用handler
func (g *RouterGroup) Use(handlers ...HandleFunc) {  
    g.middleware = append(g.middleware, handlers...)  
}
func (c *Context) Next() {  
    c.index++  
    s := len(c.handlers)  
    for ; c.index < s; c.index++ {  
        c.handlers[c.index](c)  
    }  
}
func (r *Router) Handle(c *Context) {  
    n, params := r.GetRouter(c.Method, c.Path)  
    if n != nil {  
        c.Params = params  
        //这里要注意因为是动态匹配要用n.patten不能用c.Path 因为Path是变化的  
        key := c.Method + "-" + n.patten  
        c.handlers = append(c.handlers, r.handlers[key])  
    } else {  
        c.handlers = append(c.handlers, func(ctx *Context) {  
            c.String(http.StatusNotFound, "404 page not find %s\n", c.Path)  
        })  
    }  
    c.Next()  
}

测试

user := e.Group("/user")  
{  
    user.GET("/info", func(ctx *Context) {  
        ctx.HTML(200, "用户信息")  
    })  
    v1 := user.Group("/v1")  
    {  
        v1.GET("/info", func(ctx *Context) {  
            ctx.HTML(http.StatusOK, "v1 版本用户信息")  
        })  
        v1.Use(func(ctx *Context) {  
            now := time.Now()  
            log.Print("time:" + now.String() + "|你正在访问的路由为:" + ctx.Path)  
        })  
    }  
}
2023/10/17 11:25:14 time:2023-10-17 11:25:14.695475 +0800 CST m=+10.640291640|你正在访问的路由为:/user/v1/info
GET http://localhost:7999/user/v1/info

HTTP/1.1 200 OK
Date: Tue, 17 Oct 2023 03:25:14 GMT
Content-Length: 21
Content-Type: text/plain; charset=utf-8

v1 版本用户信息

总结

本章我们在路由分组层面实现了中间件的逻辑.