中间件
前言
在Web应用中,中间件是一个非常常见的组件,用来在请求和响应之间嵌入一些操作,比如日志记录、身份验证、错误处理等。
如果使用gin.Default()方式创建gin实例,将会包含两个中间件,一个日志记录中间件,一个异常恢复中间件。如果用gin.New()的方式示例化,将不包含中间件。
根据作用范围,可以分为三种中间件:
- 全局级,对于所有api都生效
- 路由组级,对于路由组内的所有api生效
- 路由级,只对单个api生效
下面的代码示例来自官网文档
func main() {
// Creates a router without any middleware by default
r := gin.New()
// Global middleware
// Logger middleware will write the logs to gin.DefaultWriter even if you set with GIN_MODE=release.
// By default gin.DefaultWriter = os.Stdout
r.Use(gin.Logger())
// Recovery middleware recovers from any panics and writes a 500 if there was one.
r.Use(gin.Recovery())
// Per route middleware, you can add as many as you desire.
r.GET("/benchmark", MyBenchLogger(), benchEndpoint)
// Authorization group
// authorized := r.Group("/", AuthRequired())
// exactly the same as:
authorized := r.Group("/")
// per group middleware! in this case we use the custom created
// AuthRequired() middleware just in the "authorized" group.
authorized.Use(AuthRequired())
{
authorized.POST("/login", loginEndpoint)
authorized.POST("/submit", submitEndpoint)
authorized.POST("/read", readEndpoint)
// nested group
testing := authorized.Group("testing")
testing.GET("/analytics", analyticsEndpoint)
}
// Listen and serve on 0.0.0.0:8080
r.Run(":8080")
}
一个简单的自定义中间件示例
下面是一个简单的自定义中间件示例,在控制台输出请求时间、请求耗时、请求客户端、请求方法、响应码。编辑pkg/middlewares/mids.go
type mids struct{}
func NewMids() *mids {
return &mids{}
}
func (m *mids) Simple(c *gin.Context) {
start := time.Now()
c.Next() //
current := time.Now()
status := c.Writer.Status()
method := c.Request.Method
path := c.FullPath()
clientIP := c.ClientIP()
fmt.Printf("%s | %s %s %s cost %v, status: %d\n", current.Format("2006-01-02 15:04:05"), clientIP, method, path, current.Sub(start), status)
}
编辑main.go
func main() {
mids := middlewares.NewMids()
router := gin.New()
router.Use(gin.Recovery())
router.Use(mids.Simple)
router.GET("/header", func(c *gin.Context) {
userAgent := c.GetHeader("User-Agent")
log.Info("User-Agent", "userAgent", userAgent)
c.String(http.StatusOK, userAgent)
})
router.Run("127.0.0.1:8000")
}
运行输出结果
2024-11-23 22:18:49 | 127.0.0.1 GET /header cost 512.7µs, status: 200