Gin框架系列03:换个姿势理解中间件

栏目: IT技术 · 发布时间: 4年前

什么是中间件

中间件,英译middleware,顾名思义,放在中间的物件,那么放在谁中间呢?本来,客户端可以直接请求到服务端接口。

Gin框架系列03:换个姿势理解中间件
file

现在,中间件横插一脚,它能在请求到达接口之前拦截请求,做一些特殊处理,比如日志记录,故障处理等。这就是今天要讲述的中间件,那么,它在Gin框架中是怎么使用的呢?

Gin框架系列03:换个姿势理解中间件
file

如何使用中间件

我们来看一下逢 gin 必调的方法 Default ,方法中有一个变量 engine ,它 UseLoggerRecovery 两个函数,这两个函数就是 gin 框架的日志和故障处理中间件。

func Default() *Engine {
 debugPrintWARNINGDefault()
 engine := New()
 engine.Use(Logger(), Recovery())
 return engine
}

那就很清楚了,使用中间件就是调用 Use 方法就行了呗,问题是现在除了这两个中间件还能去 Use 谁?不如咱先自己写一个中间件吧,这样比较容易理解。

写一个中间件

写啥呢,做产品讲究MVP,那咱就写个最简单的闭环,拦截请求后输出 平也最帅 的日志,产品就可以交付了。

Gin框架系列03:换个姿势理解中间件
file

写之前先研究一下官方的 LoggerRecovery 是怎么写的,好比葫芦画瓢。

func Logger() HandlerFunc {
 return LoggerWithConfig(LoggerConfig{})
}

func Recovery() HandlerFunc {
 return RecoveryWithWriter(DefaultErrorWriter)
}

原来这两个函数都返回了 HandlerFunc 类型,那我们也模仿写一个函数就好了。

func PingYe() gin.HandlerFunc {
 return func(c *gin.Context) {
  c.String(200, "平也最帅")
 }
}

很简单,写完了,可以在 main 函数中 Use 它了。

func main() {
 r := gin.Default()
 r.Use(PingYe())
 r.Run()
}

把项目跑起来,访问 localhsot:8080 看一下,帅呆了,成功渲染数据。

Gin框架系列03:换个姿势理解中间件
file

是不是太简单了?这就交差了?我还能打十个啊!?

Gin框架系列03:换个姿势理解中间件
file

看来我要把毕生所学都交给你了。

延伸阅读

Next

假如我们定义了两个中间件,一个是平也最帅,另一个是在哪里最帅。

func PingYe() gin.HandlerFunc {
 return func(c *gin.Context) {
  c.String(200, "平也最帅")
 }
}

func Where() gin.HandlerFunc {
 return func(c *gin.Context) {
  c.String(200, "在全宇宙")
 }
}

按顺序把它们分别注册到框架当中,这个时候我们猜测它会先输出 平也最帅 再输出 在全宇宙 对吧?对,确实是的。

func main() {
 r := gin.Default()
 r.Use(PingYe(), Where())
 r.Run()
}

但是,如果我在不更改注册顺序的前提下,怎么调换一下顺序,先输出 在全宇宙 再输出 平也最帅 呢?这就用到了大名鼎鼎的 Next 方法。它的作用就是先执行以下一个中间件,执行完了再回来继续执行接下来的逻辑。记得是在中间件中调用哦~

func PingYe() gin.HandlerFunc {
  return func(c *gin.Context) {
    c.Next()
    c.String(200, "平也最帅")
  }
}
Gin框架系列03:换个姿势理解中间件
file

Abort

当然,除了提供 Next 方法外,理论上也应该有个中断操作吧,毕竟拿中间件来做授权验证的话,验证失败后还是希望阻断请求的。所以, Abort 就是我们要找的那个方法。拿上面的例子,在 平也最帅 的下一行调用 Abort 方法后, Where 中间件就不再生效了,于是平也只剩下了单纯的帅气。

func PingYe() gin.HandlerFunc {
 return func(c *gin.Context) {
  c.String(200, "平也最帅")
  c.Abort()
 }
}
Gin框架系列03:换个姿势理解中间件
file

局部中间件

刚才我讲的中间件是会在所有的路由上生效的,有些不需要添加中间件的路由场景就无法适应了。所以,我们需要有能为局部添加中间件的能力。

Gin框架系列03:换个姿势理解中间件
file

我们先实现给某个接口单独加中间件,所以先得定义两个接口 knowunknown ,分别代表认识平也与不认识两个场景,鉴于认识后才知道平也是全宇宙最帅的,所以要绑中间件,不认识就算了。实现方式非常简单,往路由后面的参数拼命加中间件就好了。

r.GET("know", PingYe(), Where())
r.GET("unknown", func(c *gin.Context) {
  c.String(200, "???")
})

除了针对某个接口添加中间件外,还可以针对一组接口添加,同样调用 Use 方法即可。

v1 := r.Group("v1")
v1.Use(PingYe(), Where())
{
  v1.GET("/know", func(c *gin.Context) {
    c.String(200, "know")
  })
  v1.GET("/unknown", func(c *gin.Context) {
    c.String(200, "unknown")
  })
}

HTTP基本认证

基本认证,又称 BasicAuth ,加了基本认证的接口,会让你在访问接口时提供用户名与密码。

Gin框架系列03:换个姿势理解中间件
file

对于浏览器用户,为了用户的体验会自动弹出登录框,而在其他场景下是没有的,那在哪里输入账号密码呢?实际上,它是通过头信息传输的,头信息里有一个固定的格式来代表基本认证。

Authorization: Basic <凭证>

凭证部分是是用户名和密码组合的 base64 编码,两者以冒号方式拼接。然鹅, gin 框架的 BaseAuth 中间件早已准备好了一切,它可以短短几行代码就能解析基本认证的信息。

func main() {
 r := gin.Default()
 r.Use(gin.BasicAuth(gin.Accounts{
  "pingye": "123",
 }))
 r.GET("/secrets", func(c *gin.Context) {
  user := c.MustGet(gin.AuthUserKey).(string)
  c.String(200, user+"已登录成功")
 })
 r.Run()
}

示例中的部分代码可能有些同学不太明白,比如 BasicAuth 方法中的参数,因为基本认证需要账号和密码对吧,所以我们可以利用 gin.Accounts 方便的配置好需要验证的账号密码, gin.Accounts 是一个map类型,键代表用户名,值代表密码,当然可以设置不止一个键值对,根据你的喜好自行设置。

代码中还出现了 c.MustGet 方法,这个方法的作用就是一定要取到某个参数,取不到就不干了 panic ,取的是什么呢?就是 gin.AuthUserKey ,在官方中的解释是基本认证中用户凭证的 cookie 名称。

// AuthUserKey is the cookie name for user credential in basic auth.
const AuthUserKey = "user"

Gin框架系列03:换个姿势理解中间件


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

网飞传奇

网飞传奇

[美]吉娜·基廷 / 谭永乐 / 中信出版社 / 2014-1-1 / 42

飞的历史充满了传奇色彩,它的崛起伴随着复杂斗争、幸运转折、个人背叛……它自身的历史比它出租的那些电影还要更富有戏剧性。网飞在1997年建立,而建立的原因仅仅是因为创始人伦道夫和哈斯廷斯没有按时归还租借的DVD,还要缴纳因此而产生的滞纳金。 1999年,网飞公司摒弃了百视达的“每片付租”模式,转而采用了一种订阅模式:用户只需要支付固定费用,就能尽情租片观赏,免去了到期还片日、滞纳金、运费和手续......一起来看看 《网飞传奇》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

在线进制转换器
在线进制转换器

各进制数互转换器