gin中间件

1.中间件简介

概念

  1. 中间件本质上是一个handler,可以作用在单路由,路由组,全局engine上
  2. 中间件handler可以有多个,放在正式处理业务逻辑的handler之前,处理公共业务逻辑,类似权限验证,耗时统计,数据分页,记录日志等等

创建以及注册

  1. 创建一个handler(一般以闭包的方式)
  2. 注册可以通过engine,路由组,单个路由

engine.next()和engine.abort()

  • 本质上就是一个函数嵌套调用的过程
  1. engine.next()
    从当前handler的调用位置跳到下一个handler执行,执行完下一个handler(如果没有再次调用next,否则继续往下执行),再返回上一个next调用位置继续往下执行
  2. 用于abort此前调用的next()

engine.set()和engine.get()

  1. 用于中间件(handler之间的通信),可以是handler之内,也可以是之间.
  2. 先set再get, 注意handler中间的next调用顺序,例如:m1(get,next) m2(next) m3(set,abort)是在m3中set的,而get实在m1中的,就是因为next调用的原因.
  • 好了不bb了直接上代码

实现代码

package basic

import (
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
)
// 用于模拟数据库的用户数据
type userinfos struct {
	username string
	password string
}

// 计时器中间件
// 这里使用闭包的语法,逻辑是:如果需要启用该中间件则进入计时分支,否则什么也不干
func middlerwareTimer(enableTimer bool) gin.HandlerFunc {
	return func(c *gin.Context) {
		if enableTimer {
			start := time.Now()
			c.Next()
			stop := time.Since(start)
			c.JSON(http.StatusOK, gin.H{
				"elapsed time": stop.String(),
			})
		}
	}
}

// 身份认证中间件
// 1. 初始化数据库(生产环境就是连接数据库)
// 2. 如果开启认证则query获取用户输入的参数,遍历users,如果有该用户的参数信息,则set一个kv,跑完循环get这个k,如果存在则(next)放行,反之则(abort);
// 3. 如果不开启认证 --> (next)放行
func middlerwareAuth(enableAuth bool) gin.HandlerFunc {
	// 初始化数据库
	users := []userinfos{
		{username: "shadowzhang", password: "123"},
		{username: "squallzhang", password: "520"},
		{username: "mikahai", password: "1314"},
	}
	return func(c *gin.Context) {
		if enableAuth { // 开启认证则进行认证
			username := c.Query("username")
			password := c.Query("password")
			for _, v := range users {
				if v.username == username && v.password == password {
					c.Set("exist", 1) // 设置键值对
				}
			}
			if _, exist := c.Get("exist"); exist { // 获取键值对
				c.Next() // 认证通过则放行(执行后续handler)
			} else {
				c.JSON(http.StatusUnauthorized, gin.H{
					"msg": "验证未通过",
				})
				c.Abort() // 认证不通过则不执行后续handler
			}
		} else {
			c.Next() // 不开启认证则放行(执行后续handler)
		}
	}
}

// 返回一个hello
func middlerwareHello(enableHelloWorld bool) gin.HandlerFunc {
	return func(c *gin.Context) {
		if enableHelloWorld {
			c.JSON(http.StatusOK, gin.H{
				"msg": "hello world!",
			})
		}
	}
}

func Middlerware() {
	e := gin.Default() // default默认添加了Logger和Recover的全局handler

	// 全局注册中间件
	e.Use(middlerwareTimer(false), middlerwareHello(true), middlerwareAuth(false))

	// 单路由注册中间件
	// curl -X GET localhost:9999/singleRoute?username=shadowzhang\&password=123
	// {"msg":"hello world!"}{"mode":"single"}
	// curl -X GET localhost:9999/singleRoute?username=mikahai\&password=10086
	// {"msg":"hello world!"}{"msg":"验证未通过"}
	e.GET("/singleRoute", middlerwareAuth(true), func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"mode": "single",
		})
	})

	// 路由组注册中间件
	// curl -X GET localhost:9999/groupRoute/branch1?username=shadowzhang\&password=123
	// {"msg":"hello world!"}{"method":"GET"}{"elapsed time":"6.499µs"}
	routeGroup := e.Group("/groupRoute")
	routeGroup.Use(middlerwareTimer(true))
	routeGroup.Any("/branch1", func(c *gin.Context) {
		switch c.Request.Method {
		case http.MethodGet:
			c.JSON(http.StatusOK, gin.H{
				"method": "GET",
			})
		case http.MethodPost:
			c.JSON(http.StatusOK, gin.H{
				"method": "POST",
			})
		case http.MethodPut:
			c.JSON(http.StatusOK, gin.H{
				"method": "PUT",
			})
		case http.MethodDelete:
			c.JSON(http.StatusOK, gin.H{
				"method": "DELETD",
			})
		}
	})

	e.Run("0.0.0.0:9999")
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值