中间件用过么?
Middleware是Web的重要组成部分,中间件(通常)是一小段代码,它们接受一个请求,对其进行处理,每个中间件只处理一件事情,完成后将其传递给另一个中间件或最终处理程序,这样就做到了程序的解耦。
全局中间件
- 所有的请求都要经过此中间件
package main
import (
"fmt"
"time"
"github.com/gin-gonic/gin"
)
// 定义中间
func MiddleWare() gin.HandlerFunc {
return func(c *gin.Context) {
t := time.Now()
fmt.Println("中间件开始执行了")
// 设置变量到Context的key中,可以通过Get()取
c.Set("request", "中间件")
status := c.Writer.Status()
fmt.Println("中间件执行完毕", status)
t2 := time.Since(t)
fmt.Println("time:", t2)
}
}
func main() {
// 1.创建路由, 访问路由时经过此中间件
// 默认使用了2个中间件Logger(), Recovery()
r := gin.Default()
// 注册中间件
r.Use(MiddleWare())
{
r.GET("/ce", func(c *gin.Context) {
// 取在中间件设置的值,如果取到了说明中间件应用成功
req, _ := c.Get("request")
fmt.Println("request:", req)
// 页面接收
c.JSON(200, gin.H{"request": req})
})
}
r.Run()
}
总结:我们在访问这个路由的时候,会执行里面的函数,返回想要的数据,中间件的作用就是在执行这个路由的函数之前所做的事情!
那么中间件一般可以做一些什么呢?
比如在微服务当中可以做一些 jwt 权限验证
// CommonJwtAuthMiddleware : with jwt on the verification, no jwt on the verification
type CommonJwtAuthMiddleware struct {
secret string
}
func NewCommonJwtAuthMiddleware(secret string) *CommonJwtAuthMiddleware {
return &CommonJwtAuthMiddleware{
secret: secret,
}
}
func (m *CommonJwtAuthMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if len(r.Header.Get("Authorization")) > 0 {
//has jwt Authorization
authHandler := handler.Authorize(m.secret)
authHandler(next).ServeHTTP(w, r)
return
} else {
//no jwt Authorization
next(w, r)
}
}
}
总结:本例子是微服务的例子,在访问某一个接口前先检验jwt验证
中间件中最重要的Next() 方法
package main
import (
"fmt"
"time"
"github.com/gin-gonic/gin"
)
// 定义中间
func MiddleWare() gin.HandlerFunc {
return func(c *gin.Context) {
t := time.Now()
fmt.Println("中间件开始执行了")
// 设置变量到Context的key中,可以通过Get()取
c.Set("request", "中间件")
// 执行函数
c.Next()
// 中间件执行完后续的一些事情
status := c.Writer.Status()
fmt.Println("中间件执行完毕", status)
t2 := time.Since(t)
fmt.Println("time:", t2)
}
}
func main() {
// 1.创建路由
// 默认使用了2个中间件Logger(), Recovery()
r := gin.Default()
// 注册中间件
r.Use(MiddleWare())
// {}为了代码规范
{
r.GET("/ce", func(c *gin.Context) {
// 取值
req, _ := c.Get("request")
fmt.Println("request:", req)
// 页面接收
c.JSON(200, gin.H{"request": req})
})
}
r.Run()
}
// console result
[GIN-debug] Listening and serving HTTP on :8080
中间件开始执行了
request: 中间件
中间件执行完毕 200
time: 177.7µs
[GIN] 2022/11/02 - 20:27:50 | 200 | 190.105µs | ::1 | GET "/ce"
总结:在执行next函数的时候,中间件下面的暂时不执行了,先去路由函数执行完成了之后再去执行next后面的代码。
局部中间件
简单展示一下代码吧
r.GET("/ce", MiddleWare(), func(c *gin.Context) {}
总结:其实就是给某一个路由单独走中间件,其他路由不走这个中间件。