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

摘要:
如何使用中间件让我们来看看每次gin都必须调用的方法Default。在该方法中,有一个变量引擎,它使用Logger和Recovery函数。这两个功能是gin框架的日志记录和故障处理中间件。让我们先编写一个中间件,这样更容易理解。“)})除了为某个接口添加中间件之外,还可以通过调用Use方法为一组接口添加中间件。但是Goose,gin框架的BaseAuth中间件已经准备就绪。它只需几行代码就可以解析基本的身份验证信息。它是gin.AuthUserKey,正式解释为用户凭据的cookie名称在基本认证中。

什么是中间件

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

file

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

file

如何使用中间件

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

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

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

写一个中间件

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

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看一下,帅呆了,成功渲染数据。

file

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

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, "平也最帅")
  }
}

file

Abort

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

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

file

局部中间件

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

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,加了基本认证的接口,会让你在访问接口时提供用户名与密码。

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"

Go语言库示例开源项目「golang-examples」欢迎star~

https://github.com/pingyeaa/golang-examples

感谢大家的观看,如果觉得文章对你有所帮助,欢迎关注公众号「平也」,聚焦Go语言与技术原理。
关注我

免责声明:文章转载自《Gin框架系列03:换个姿势理解中间件》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇关于序列化:把某个对象序列化成字节流express + multer 文件上传入门下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

10个顶级的CSS和Javascript动画框架推荐

在网站中嵌入动画已成为近年来的一个设计趋势,许多公司都已开始转向并拥抱HTML5、CSS3和JavaScript这个技术“三人组”。尽管这些技术还不能制作一些非常复杂的动画(像flash所实现的),但是如果拥有好的想法及创造性思维,使用它们制作的即便是一些简单的动画也足以打动我们。 而且,随着CSS3技术的发展,CSS3动画日益流行。目前,WebKit浏览...

从零开始手写 dubbo rpc 框架

rpc rpc 是基于 netty 实现的 java rpc 框架,类似于 dubbo。 主要用于个人学习,由渐入深,理解 rpc 的底层实现原理。 前言 工作至今,接触 rpc 框架已经有很长时间。 但是对于其原理一直只是知道个大概,从来没有深入学习过。 以前一直想写,但由于各种原因被耽搁。 技术准备 Java 并发实战学习 TCP/IP 协议学习笔记...

使用Java语言开发机器学习框架和参数服务器

https://github.com/wudikua/ps 本项目是我自己动手实现的机器学习训练框架,代码简单,有很多不完善,但是也保留了最小可用功能 通过自己编写这个项目,可以帮助自己入门机器学习 准备 1. 学习梯度下降法训练LR模型原理,了解机器学习一般的套路 2. 学习神经网络的模型结构,正向传导和反向传导 3. 学习一些python写的神经网络,...

java轻量级IOC框架Guice

Google-Guice入门介绍(较为清晰的说明了流程):http://blog.csdn.net/derekjiang/article/details/7231490 使用Guice,需要添加第三方的包(guice-3.0.jar和javax.inject.jar) 链接:https://pan.baidu.com/s/1vU9zwrklTPS-YTw...

搭建你的Spring.Net+Nhibernate+Asp.Net Mvc 框架 (二)创建你的项目

本篇文章的目的:首先是创建解决方案。并创建相关的项目。先介绍一下项目的各自的作用: 从数据库层到表示层依次为: 数据库层:          1、接口IDao层:IDao          2、Dao层实现:HibernateDao和SqlDao               HibernateDao:由Hibernate实现的IDao部分         ...

移动端可视化框架antv f2出现两个legend选项

前天遇到个坑,把我给坑死了 ,在帮朋友做一个微信公众号的项目,使用的vue全家桶,有个模块需要用到数据可视化展现,之前做项目的时候用过antv,比较熟悉,因为是移动端的项目,所以用的是antv f2这个可视化框架,按照之前写的方式都做完之后,最后发现下面出现了两个相同的legend,找了半天也没发现问题出在哪,百思不得其解 watch:{ sta...