1.中间件简介
概念
- 中间件本质上是一个handler,可以作用在单路由,路由组,全局engine上
- 中间件handler可以有多个,放在正式处理业务逻辑的handler之前,处理公共业务逻辑,类似权限验证,耗时统计,数据分页,记录日志等等
创建以及注册
- 创建一个handler(一般以闭包的方式)
- 注册可以通过engine,路由组,单个路由
engine.next()和engine.abort()
- engine.next()
从当前handler的调用位置跳到下一个handler执行,执行完下一个handler(如果没有再次调用next,否则继续往下执行),再返回上一个next调用位置继续往下执行 - 用于abort此前调用的next()
engine.set()和engine.get()
- 用于中间件(handler之间的通信),可以是handler之内,也可以是之间.
- 先set再get, 注意handler中间的next调用顺序,例如:m1(get,next) m2(next) m3(set,abort)是在m3中set的,而get实在m1中的,就是因为next调用的原因.
实现代码
package basic
import (
"net/http"
"time"
"github.com/gin-gonic/gin"
)
type userinfos struct {
username string
password string
}
func middlerwareTimer(enableTimer bool) gin.HandlerFunc {
return func(c *gin.Context) {
if enableTimer {
start := time.Now()
c.Next()
stop := time.Since(start)
c.JSON(http.StatusOK, gin.H{
"elapsed time": stop.String(),
})
}
}
}
func middlerwareAuth(enableAuth bool) gin.HandlerFunc {
users := []userinfos{
{username: "shadowzhang", password: "123"},
{username: "squallzhang", password: "520"},
{username: "mikahai", password: "1314"},
}
return func(c *gin.Context) {
if enableAuth {
username := c.Query("username")
password := c.Query("password")
for _, v := range users {
if v.username == username && v.password == password {
c.Set("exist", 1)
}
}
if _, exist := c.Get("exist"); exist {
c.Next()
} else {
c.JSON(http.StatusUnauthorized, gin.H{
"msg": "验证未通过",
})
c.Abort()
}
} else {
c.Next()
}
}
}
func middlerwareHello(enableHelloWorld bool) gin.HandlerFunc {
return func(c *gin.Context) {
if enableHelloWorld {
c.JSON(http.StatusOK, gin.H{
"msg": "hello world!",
})
}
}
}
func Middlerware() {
e := gin.Default()
e.Use(middlerwareTimer(false), middlerwareHello(true), middlerwareAuth(false))
e.GET("/singleRoute", middlerwareAuth(true), func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"mode": "single",
})
})
routeGroup := e.Group("/groupRoute")
routeGroup.Use(middlerwareTimer(true))
routeGroup.Any("/branch1", func(c *gin.Context) {
switch c.Request.Method {
case http.MethodGet:
c.JSON(http.StatusOK, gin.H{
"method": "GET",
})
case http.MethodPost:
c.JSON(http.StatusOK, gin.H{
"method": "POST",
})
case http.MethodPut:
c.JSON(http.StatusOK, gin.H{
"method": "PUT",
})
case http.MethodDelete:
c.JSON(http.StatusOK, gin.H{
"method": "DELETD",
})
}
})
e.Run("0.0.0.0:9999")
}