HTTP框架之中间件设计 | 青训营

77 阅读2分钟

中间件设计

1. 中间件概念

· 在请求和响应之间执行一系列的操作,可以用于处理身份验证、异常处理及日志打印等任务

· 一个或一组函数,接受请求对象、响应对象和一个next回调函数作为参数。

2. 中间件需求

· 配合Hander实现一个完整的请求处理生命周期

· 拥有预处理逻辑和后处理逻辑

· 可以注册多中间件

· 对上层模块用户逻辑模块易用

3. 实例:打印每个请求的request和response

· 不使用中间件:在每个请求的开始和结束都加上logs.Infof()

· 使用中间件:

```go
func main(){
    h := server.New()
    
    //使用中间件来处理请求和响应
    h.Use(func(c context.Context, ctx *app.RequestContext){
        //打印接收到的原始请求信息
        logs.Infof("Received RawRequest: %s", ctx.Request.RawRequest())
        
        //将请求传递给下一个处理程序。该函数会暂停当前中间件函数的执行,并将控制权交给下一个中间件函数或目标处理程序。当目标处理程序执行完毕后会按照调用链的相反顺序继续执行。
        ctx.Next(c)
        
        //打印发送的原始响应信息
        logs.Infof("Send RawResponse: %s", ctx.Response.RawResponse())
    })
    
    //定义一个处理登录请求的路由和处理函数
    h.POST("/login", func(c context.Context, ctx *app.RequestContext){
        //some biz logic
        ctx.JSON(200, "OK")
    })
    
    //定义一个处理登出请求的路由和处理函数
    h.POST("/logout", func(c context.Context, ctx *app.RequestContext){
        //some biz logic
        ctx.JSON(200, "OK")
    })
    
    //启动HTTP服务器并开始监听请求
    h.Spin()
}
```

中间件函数的执行过程可以看作一个“洋葱模型”,请求从外部逐层向内部传递,然后再从内部逐层向外部传递。ctx.Next(c)函数的作用是将请求传递给下一个中间件函数或目标处理程序。它并不是一个跳转函数,而是一个将控制权传给下一个处理程序的方法。

4. 中间件设计

· 不调用Next:初始化逻辑且不需要在同一调用栈

· 调用Next:后处理逻辑或需要在同一调用栈上

路由设计

1. 框架路由实际上就是为URL匹配对应的处理函数

· 静态路由:/a/b/c

· 参数路由:/a/:id/c、/*all

· 路由修复:/a/b <-> /a/b/

· 冲突路由及优先级

· 匹配HTTP方法

· 多处理函数:方便添加中间件

2. 路由设计

· 前缀匹配树