gin中间件

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")
}

已标记关键词 清除标记