Go Echo 学习笔记(十二)中间件
中间件
中间件是在 HTTP 请求-响应处理周期过程中切入的一个函数(可以拦截http请求-响应生命周期的特殊函数),具有对 Echo#Context
的访问权,可以用于执行特定的操作,例如,记录每个请求或者限制请求的数量。
在请求-响应生命周期中可以注册多个中间件,每个中间件执行不同的功能,一个中间执行完再轮到下一个中间件执行。当所有的中间件执行完毕之后才会去执行请求处理函数(Hanlder)。
下图是中间件的运行流程:
Echo 中注册一个中间件所使用的方法是 Echo#Use()
,并且只有在完成注册之后的中间件才会在请求处理过程中被调用。
中间件具有的级别有:根级别(路由处理之前、理路由处理之后)、组级别、路径级别。
根级别(路由处理之前)
Echo#Pre()
支持注册一个中间件在请求被处理之前执行,这类中间件有助于对请求属性进行任意更改操作,但是由于路由处理程序尚未处理请求,因此该级别的中间件将无法从 echo.Context
访问任何与路径相关的API。
下面的这些内置的中间件应该被注册在这个级别:
- HTTPSRedirect:重定向中间件,http强制跳转至https
- HTTPSWWWRedirect:重定向中间件,https www跳转
- WWWRedirect:重定向中间件,www跳转
- NonWWWRedirect:重定向中间件,直接跳转
- AddTrailingSlash
- RemoveTrailingSlash
- MethodOverride
- Rewrite:url重定向中间,我们可以用于将一个url重定向到另外一个url。
根级别(路由处理之后)
大多数情况下使用 Echo#Use()
注册的中间件都是属于这个级别的,也就是在路由处理之后执行,这些中间件可以支持访问 echo.Context
相关的API。
下面的这些内置的中间件应该被注册在这个级别:
- BodyLimit
- Logger:Logger中间件主要用于打印http请求日志。
- Gzip
- Recover:Recover中间件,主要用于拦截panic错误并且在控制台打印错误日志,避免echo程序直接崩溃,一般echo应用都会注册Recover中间件,避免程序崩溃退出。
- BasicAuth
- JWTAuth
- Secure
- CORS
- Static
组级别
可以针对一个 Echo 中的 Group 创建设置对应的中间件:
// 方法一
e := echo.New()
admin := e.Group("/admin", middleware.BasicAuth())
// 方法二
e := echo.New()
admin := e.Group("/admin")
admin.Use(middleware.BasicAuth())
路径级别
当注册一个路由之后也可以专门针对该路由设置对应的中间件:
e := echo.New()
e.GET("/", <Handler>, <Middleware...>)
跳过中间件
某些情况下需要跳过某些中间件,这种情况下可以在注册中间件的时候可以针对 middleware.LoggerConfig
设置其中的 Skipper func(c echo.Context) bool
方法来实现:
e := echo.New()
// 针对请求前缀为 localhost 的请求跳过Logger中间件
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
Skipper: func(c echo.Context) bool {
if strings.HasPrefix(c.Request().Host, "localhost") {
return true
}
return false
},
}))
自定义中间件
下面以一个简单的统计访问量的例子介绍如何自定义中间件:
package main
import (
"net/http"
"github.com/labstack/echo"
)
//记录访问量
var totalRequests = 0
//中间件函数
func Count(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
//在这里处理拦截请求的逻辑
//累计访问量
totalRequests++
//在响应头中输出访问量
c.Response().Header().Add("requests", fmt.Sprintf("%d", totalRequests))
//执行下一个中间件或者执行控制器函数, 然后返回执行结果
return next(c)
}
}
func main() {
//初始化echo实例
e := echo.New()
//注册中间件
e.Use(Count)
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.Logger.Fatal(e.Start(":1323"))
}