文章目录
gin中间件的作用
- 请求到达http请求处理方法之前,拦截请求:
- 认证
- 权限校验
- 限流
- 数据过滤
- ip白名单
- 处理完请求后,拦截响应,并进行相应的处理
- 统一添加响应头
- 数据过滤
gin中间件的定义
中间件就是一个以gin.Context为形参的函数:
type HandlerFunc func(*Context)
gin内置中间件
func BasicAuth(accounts Accounts) HandlerFunc
func BasicAuthForRealm(accounts Accounts, realm string) HandlerFunc
func Bind(val interface{}) HandlerFunc //拦截请求参数并进行绑定
func ErrorLogger() HandlerFunc //错误日志处理
func ErrorLoggerT(typ ErrorType) HandlerFunc //自定义类型的错误日志处理
func Logger() HandlerFunc //日志记录
func LoggerWithConfig(conf LoggerConfig) HandlerFunc
func LoggerWithFormatter(f LogFormatter) HandlerFunc
func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc
func Recovery() HandlerFunc
func RecoveryWithWriter(out io.Writer) HandlerFunc
func WrapF(f http.HandlerFunc) HandlerFunc //将http.HandlerFunc包装成中间件
func WrapH(h http.Handler) HandlerFunc //将http.Handler包装成中间件
gin中间件的位置
- 全局
- 路由组
- 路由明细
gin中间件的使用
gin默认使用中间件
func Default() *Engine {
debugPrintWARNINGDefault()
engine := New()
engine.Use(Logger(), Recovery())//使用Recovery和Logger中间
return engine
}
从上面源码中可以看到,gin.Default()返回的gin.Engine已经默认使用了Recovery和Logger中间件。
当不想使用这两个中间件时,可以使用gin.New()返回一个不带中间件的gin.Engine对象:router:=gin.New()
单个路由使用中间件
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
router := gin.Default()
router.GET("/", gin.Recovery(), gin.Logger(), func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"msg": "single route"})
})
router.Run(":8080")
}
路由分组使用中间件
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
router := gin.Default()
v1 := router.Group("/v1", gin.Logger(), gin.Recovery())
{
v1.GET("/test1", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"res": "test1"})
})
v1.GET("/test2", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"res": "test2"})
})
}
router.Run(":8080")
}
全局中间件
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
router := gin.Default()
router.Use(func(c *gin.Context) {
fmt.Println("hello middleware")
})
router.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "OK"})
})
router.Run(":8080")
}
传参
//gin set get取参数
func (c *Context) Set(key string, value interface{})
func (c *Context) Get(key string) (value interface{}, exists bool) //判断key是否存在 c.Get
func (c *Context) GetBool(key string) (b bool)
func (c *Context) GetDuration(key string) (d time.Duration)
func (c *Context) GetFloat64(key string) (f64 float64)
func (c *Context) GetInt(key string) (i int)
func (c *Context) GetInt64(key string) (i64 int64)
func (c *Context) GetString(key string) (s string)
func (c *Context) GetStringMap(key string) (sm map[string]interface{})
func (c *Context) GetStringMapString(key string) (sms map[string]string)
func (c *Context) GetStringMapStringSlice(key string) (smss map[string][]string)
func (c *Context) GetStringSlice(key string) (ss []string)
func (c *Context) GetTime(key string) (t time.Time)
func (c *Context) MustGet(key string) interface{} //必须有, 否则panic
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func Middleware1(c *gin.Context) {
c.Set("key1", 123)
c.Set("key2", "renwoxing")
}
func main() {
router := gin.New()
router.GET("/", Middleware1, func(c *gin.Context) {
key1 := c.GetInt("key1")
key2 := c.GetString("key2")
c.JSON(http.StatusOK, gin.H{
"key1": key1,
"key2": key2,
})
})
router.Run(":8080")
}
自定义中间件
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
router := gin.Default()
router.Use(MyMiddleware())
router.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"res": "user define middleware"})
})
router.Run(":8080")
}
func MyMiddleware() gin.HandlerFunc {
//中间件逻辑处理
fmt.Println("todo....")
return func(c *gin.Context) {
fmt.Println("return middleware")
}
}
使用gin.BasicAutn
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
// 模拟数据
var secrets = gin.H{
"zhangsan": gin.H{"email": "zhangsan@example.com", "phone": "123456"},
"lisi": gin.H{"email": "lisi@example.com", "phone": "123456"},
"wangwu": gin.H{"email": "wangwu@example.com", "phone": "123456"},
}
func main() {
router := gin.Default()
router.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, secrets)
})
// 为/admin路由组设置auth, 路由组使用 gin.BasicAuth() 中间件
auth := router.Group("/admin", gin.BasicAuth(gin.Accounts{
"zhangsan": "zhangsan",
"lisi": "lisi",
"wangwu": "wangwu",
}))
// /admin/secrets 端点
auth.GET("/secrets", func(c *gin.Context) {
//获取用户名
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"})
}
})
router.Run(":8080")
}
计算响应时间
package main
import (
"github.com/gin-gonic/gin"
"log"
"net/http"
"time"
)
func statCost() gin.HandlerFunc {
return func(c *gin.Context) {
t := time.Now()
c.Set("test", "123456")
// 请求前逻辑
c.Next()
//请求后逻辑
latency := time.Since(t)
log.Printf("total spend time: %d us", latency/1000)
}
}
func main() {
router := gin.Default()
router.Use(statCost())
router.GET("/", func(c *gin.Context) {
test := c.MustGet("test").(string)
log.Println(test)
c.JSON(http.StatusOK, gin.H{"msh": "success"})
})
router.Run(":8080")
}