📦 Go1.22.5Gin1.10.0

🌟 什么是中间件

⭐️ 在Gin框架中,中间件(Middleware)是一种特殊类型的处理函数,它在 HTTP请求-响应生命周期中的某个点被调用,允许你在实际处理请求的主逻辑之前或之后插入自定义的处理逻辑。中间件通常用于执行一些横切关注点(c ross-cutting concerns)的任务,例如身份验证、日志记录、请求/响应修改、错误处理、跟踪、速率限制等,这些任务往往是许多路由共有的,因此通过中间件实现可以避免重复代码并提高代码的可维护性。

⭐️ 大白话就是在你的请求、响应的中间添加一个中间件,让中间件处理这些请求或响应

🌟 使用中间件

⭐️ 在之前的代码中 Default 使用 LoggerRecovery 中间件

//创建gin server服务
r := gin.Default()

如果你不想使用默认的中间件就可以使用 New来创建

ginServer := gin.New()

创建之后使用 Use来使用中间件,Gin中提供了很多中间件:

中间件名称 所属包路径 作用
Logger github.com/gin-gonic/gin/contrib/logger 记录请求日志,包括请求方法、路径、状态码等信息。
Recovery github.com/gin-gonic/gin/contrib/recovery 捕获和恢复 panic,防止服务器崩溃。
Static github.com/gin-gonic/gin 提供静态文件服务。
Favicon 无固定包路径,可自定义 处理 favicon.ico 请求。
NoRoute github.com/gin-gonic/gin 处理所有未匹配路由的请求,通常返回 404 错误。
NoMethod github.com/gin-gonic/gin 处理不支持的 HTTP 方法请求,通常返回 405 错误。
BasicAuth github.com/gin-gonic/gin/contrib/auth 实现 HTTP 基本认证。
Secure github.com/gin-contrib/secure 提供安全特性,如 HTTPS 重定向和内容安全策略。
Gzip github.com/gin-contrib/gzip 启用 gzip 压缩响应体。
Cors github.com/gin-contrib/cors 配置跨源资源共享(CORS)。
RateLimit github.com/gin-contrib/ratelimit 实现请求限流。
JWTAuth github.com/gin-contrib/jwt 集成 JSON Web Token(JWT)认证。
func main() {
	//创建gin 服务
	ginServer := gin.New()

	//使用中间件
	ginServer.Use(gin.Logger(), gin.Recovery())

	//路由
	ginServer.GET("/home", homeHandle)

	//启动服务
	ginServer.Run(":8084")
}

此时你去访这个地址,终端上就会显示访问路由的信息,使用的使用 Logger中间件

image-20240622151341318

🌟 全局中间件

也就是作用域在全部路由上

🍵 NoRoute

1️⃣ 它的使用方式不是使用 Use使用,在定义它之后一档用户访问了一个不存在的界面就会调用它

package main

import "github.com/gin-gonic/gin"

func main() {
	//创建gin 服务
	ginServer := gin.New()

	//使用中间件
	ginServer.Use(gin.Logger(), gin.Recovery())
	//NoRoute
	ginServer.NoRoute(func(context *gin.Context) {
		context.String(404, "没有这个页面!")
	})

	//路由
	ginServer.GET("/home", homeHandle)

	//启动服务
	ginServer.Run(":8084")
}

func homeHandle(context *gin.Context) {
	context.String(200, "进入路由成功!!")
}

2️⃣ 测试:

image-20240622153031558

🍵 NoMethod

它的使用方法和 NoRoute一样,但是我并没有实验成功,不知道为什么

	//NoMethod
	ginServer.NoMethod(func(context *gin.Context) {
		context.String(405, "请求方法错误!")
	})

🌟 局部中间件

局部中间件就是作用域在单个路由或者一个路由组

🍵 BasicAuth

1️⃣ 它提供一个简单的认证服务,下面这个代码是使用 gin.BasicAuth() 作为局部中间件来使用,这里是使用在路由组中的,使用它接收一个 Accounts类型这个类型就是 map[string]string,写入格式为 "user": "password"

// 模拟一些私人数据
var secrets = gin.H{
	"foo":    gin.H{"email": "foo@bar.com", "phone": "123433"},
	"austin": gin.H{"email": "austin@example.com", "phone": "666"},
	"lena":   gin.H{"email": "lena@guapa.com", "phone": "523443"},
}

func main() {
	r := gin.Default()

	// 路由组使用 gin.BasicAuth() 中间件
	// gin.Accounts 是 map[string]string 的一种快捷方式
	authorized := r.Group("/admin", gin.BasicAuth(gin.Accounts{
		"foo":    "bar",
		"austin": "1234",
		"lena":   "hello2",
		"manu":   "4321",
	}))

	// /admin/secrets 端点
	// 触发 "localhost:8080/admin/secrets
	authorized.GET("/secrets", func(c *gin.Context) {
		// 获取用户,它是由 BasicAuth 中间件设置的
		user := c.MustGet(gin.AuthUserKey).(string)
		if secret, ok := secrets[user]; ok {
			c.JSON(http.StatusOK, gin.H{"user": user, "secret": secret})
		} else {
			c.JSON(http.StatusOK, gin.H{"user": user, "secret": "NO SECRET :("})
		}
	})

	// 监听并在 0.0.0.0:8080 上启动服务
	r.Run(":8084")
}

然后在 /secrets 路由的处理器中,通过 gin.AuthUserKey获取用户,gin.AuthUserKey也就是 "user"字符串的一个别名

// AuthUserKey is the cookie name for user credential in basic auth.
const AuthUserKey = "user"

然后读取之前定义的 map中的数据

2️⃣ 测试结果

测试不存在信息的用户

image-20240622172118714

测试存在信息的用户

image-20240622172144859

🌟 自定义中间件

用户也可以自定义中间件,可以使用 Next,Abort等方法对路由采取操作下面拿官网代码作为演示

1️⃣ 这个代码的意思是在请求来到前执行设置 example的参数,Next之前表示请求前,后面就表示请求后

func Logger() gin.HandlerFunc {
	return func(c *gin.Context) {
		t := time.Now()

		// 设置 example 变量
		c.Set("example", "12345")

		// 请求前

		c.Next()

		// 请求后
		latency := time.Since(t)
		log.Print(latency)

		// 获取发送的 status
		status := c.Writer.Status()
		log.Println(status)
	}
}

func main() {
	r := gin.New()
	r.Use(Logger())

	r.GET("/test", func(c *gin.Context) {
		example := c.MustGet("example").(string)

		// 打印:"12345"
		log.Println(example)
	})

	// 监听并在 0.0.0.0:8080 上启动服务
	r.Run(":8080")
}

2️⃣ 在加一个网上找到的一个,验证 token

package main

import (
  "github.com/gin-gonic/gin"
)

func JwtTokenMiddleware(c *gin.Context) {
  // 获取请求头的token
  token := c.GetHeader("token")
  // 调用jwt的验证函数
  if token == "1234" {
    // 验证通过
    c.Next()
    return
  }
  // 验证不通过
  c.JSON(200, gin.H{"msg": "权限验证失败"})
  c.Abort()
}

func main() {
  router := gin.Default()

  api := router.Group("/api")

  apiUser := api.Group("")
  {
    apiUser.POST("login", func(c *gin.Context) {
      c.JSON(200, gin.H{"msg": "登录成功"})
    })
  }
  apiHome := api.Group("system").Use(JwtTokenMiddleware)
  {
    apiHome.GET("/index", func(c *gin.Context) {
      c.String(200, "index")
    })
    apiHome.GET("/home", func(c *gin.Context) {
      c.String(200, "home")
    })
  }

  router.Run(":8080")
}