golang,go,博客,开源,编程
在 Gin 框架中,中间件是处理请求和响应的函数,可以在请求进入路由处理函数之前或响应返回客户端之前执行。中间件广泛用于执行公共任务,例如身份验证、日志记录、错误处理、请求限流等。
开发一个 Gin 中间件的基本步骤如下:
*gin.Context
作为参数的函数。你可以在中间件中进行一些操作,然后调用 c.Next()
将控制权交给下一个中间件或路由处理函数。Gin 中间件函数的结构如下:
func MyMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 执行中间件的操作,比如日志记录、权限验证等
// 调用 c.Next() 将请求传递给后续的中间件/处理函数
c.Next()
// 在请求完成后,进行响应后的操作,比如记录响应时间等
}
}
下面我们通过开发几个简单的中间件示例,帮助你理解如何使用和编写 Gin 中间件。
这个中间件记录每个请求的基本信息,例如请求方法、请求路径和请求时间。
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"time"
)
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
// 记录请求开始时间
start := time.Now()
// 继续处理请求
c.Next()
// 请求完成后,记录日志
duration := time.Since(start)
fmt.Printf("Request %s %s took %v\n", c.Request.Method, c.Request.URL.Path, duration)
}
}
func main() {
r := gin.Default()
// 使用日志记录中间件
r.Use(Logger())
r.GET("/hello", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "Hello, World!"})
})
r.Run(":8080")
}
在这个示例中,每次访问 /hello
路径时,都会输出类似下面的日志:
Request GET /hello took 1.223ms
在这个示例中,我们开发一个简单的身份验证中间件,检查请求头中是否有有效的 Token。如果没有,则返回 401 错误。
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("Authorization")
// 假设 Token 是 "Bearer mytoken123"
if token != "Bearer mytoken123" {
c.JSON(401, gin.H{"error": "Unauthorized"})
c.Abort() // 阻止后续的处理
return
}
// 如果 Token 验证成功,继续处理请求
c.Next()
}
}
func main() {
r := gin.Default()
// 仅对 /secure 路由启用身份验证中间件
r.GET("/secure", AuthMiddleware(), func(c *gin.Context) {
c.JSON(200, gin.H{"message": "You have access to the secure route"})
})
r.GET("/public", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "This is a public route"})
})
r.Run(":8080")
}
访问 /secure
时,需要提供有效的 Authorization
头,否则会返回 401 错误。而 /public
路由不需要身份验证。
CORS(跨域资源共享)中间件用于允许跨域请求。这里是一个自定义的 CORS 中间件的示例:
func CORSMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 设置 CORS 头,允许跨域请求
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization")
// 如果是 OPTIONS 请求,则直接返回 200 响应
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(200)
return
}
// 继续处理请求
c.Next()
}
}
func main() {
r := gin.Default()
// 使用 CORS 中间件
r.Use(CORSMiddleware())
r.GET("/hello", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "Hello, World!"})
})
r.Run(":8080")
}
此中间件允许所有来源的请求,可以自定义 Access-Control-Allow-Origin
等头部,控制哪些源可以访问你的资源。
中间件可以全局使用,也可以针对某些路由或路由组使用:
将中间件应用于所有路由:
r := gin.Default()
r.Use(Logger()) // 将 Logger 中间件应用于所有路由
r.GET("/hello", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "Hello, World!"})
})
r.Run(":8080")
将中间件仅应用于某些路由:
r := gin.Default()
// 只有 /secure 路由使用 AuthMiddleware 中间件
r.GET("/secure", AuthMiddleware(), func(c *gin.Context) {
c.JSON(200, gin.H{"message": "Secure route"})
})
// /public 路由不使用任何中间件
r.GET("/public", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "Public route"})
})
r.Run(":8080")
可以为一组路由应用同一个中间件:
r := gin.Default()
// 创建一个路由组
authorized := r.Group("/admin")
authorized.Use(AuthMiddleware()) // 应用 AuthMiddleware 到这个路由组
{
authorized.GET("/dashboard", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "Welcome to the admin dashboard"})
})
}
r.Run(":8080")
gin.HandlerFunc
的函数,gin.HandlerFunc
类型的函数接受一个 *gin.Context
参数,表示请求的上下文。r.Use()
全局使用,或通过路由级别或路由组级别使用。通过自定义和组合不同的中间件,你可以很容易地扩展和定制你的 Gin 应用的功能。