6000字大章带你死磕Golang Gin中间件

在Gin的整个实现中,中间件可谓是Gin的精髓。一个个中间件组成一条中间件链,对HTTP Request请求进行拦截处理,实现了代码的解耦和分离,并且中间件之间相互不用感知到,每个中间件只需要处理自己需要处理的事情即可。今天我们就通过这篇文章,详细的介绍Gin中间的使用和原理。

通过这篇文章你可以学到:

  1. Gin中间件入门
  2. 如何使用Gin的默认中间件
  3. 中间件实现HTTP Basic Authorization
  4. 基于分组路由的中间件控制
  5. 自定义一个统计耗时的中间件
  6. 中间件的设计模式-责任链
  7. 自己实现一个责任链模式
  8. 中间件Next方法的实现原理
  9. Gin中间件源码分析
  10. Gin中间件面试要点

Gin默认中间件

在Gin中,我们可以通过Gin提供的默认函数,来构建一个自带默认中间件的*Engine

r := gin.Default()

Default函数会默认绑定两个已经准备好的中间件,它们就是Logger 和 Recovery,帮助我们打印日志输出和painc处理。

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

从中我们可以看到,Gin的中间件是通过Use方法设置的,它接收一个可变参数,所以我们同时可以设置多个中间件。

func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes

到了这里其实我们应该更加明白了,一个Gin的中间件,其实就是Gin定义的一个HandlerFunc,而它在我们Gin中经常使用,比如:

r.GET("/", func(c *gin.Context) {fmt.Println("首页")c.JSON(200, "")})

后面的func(c *gin.Context)这部分其实就是一个HandlerFunc

中间件实现HTTP Basic Authorization

HTTP Basic Authorization 是HTTP常用的认证方案,它通过Authorization 请求消息头含有服务器用于验证用户代理身份的凭证,格式为:

Authorization: Basic <credentials>

如果认证不成功,服务器返回401 Unauthorized 状态码以及WWW-Authenticate 消息头,让客户端输入用户名和密码进一步认证。

在Gin中,为我们提供了gin.BasicAuth帮我们生成基本认证的中间件,方便我们的开发。

r := gin.Default()r.Use(gin.BasicAuth(gin.Accounts{"admin": "123456",}))r.GET("/", func(c *gin.Context) {c.JSON(200, "首页")})r.Run(":8080")

我们添加一个用户名为admin,密码是123456的账户,用于HTTP 基本认证。现在我们运行启动,访问http://localhost:8080/,这时候只有我们输入正确的用户名和密码,才能看到首页,否则是看不到的,这样我们就达到了授权的目的,就是这么简单。

针对特定URL的Basic Authorization

其实在实际的项目开发中,我们基本上不太可能对所有的URL都进行认证的,一般只有一些需要认证访问的数据才需要认证,比如网站的后台,那么这时候我们就可以用分组路由来处理。

func main() {r := gin.Default()r.GET("/", func(c *gin.Context) {c.JSON(200, "首页")})adminGroup := r.Group("/admin")adminGroup.Use(gin.BasicAuth(gin.Accounts{"admin": "123456",}))adminGroup.GET("/index", func(c *gin.Context) {c.JSON(200, "后台首页")})r.Run(":8080")
}

现在我们运行访问/首页是可以正常显示的,但是我们访问/admin/index会提示输入密码,其实所有/admin/*下的URL都会让输入密码才能访问,这就是我们分组路由的好处,我们通过把中间件加到/admin这个分组路由上,就可以达到我们的目的。

通过分组路由的控制,我们可以比较灵活的设置HTTP认证,粒度可以自己随意控制。

自定义中间件

我们已经知道,Gin的中间件其实就是一个HandlerFunc,那么只要我们自己实现一个HandlerFunc,就可以自定义一个自己的中间件。现在我们以统计每次请求的执行时间为例,来演示如何自定义一个中间件。

func costTime() gin.HandlerFunc {return func(c *gin.Context) {//请求前获取当前时间nowTime := time.Now()//请求处理c.Next()//处理后获取消耗时间costTime := time.Since(nowTime)url := c.Request.URL.String()fmt.Printf("the request URL %s cost %vn", url, costTime)}
}

以上我们就实现了一个Gin中间件,比较简单,而且有注释加以说明,这里要注意的是c.Next方法,这个是执行后续中间件请求处理的意思(含没有执行的中间件和我们定义的GET方法处理),这样我们才能获取执行的耗时。也就是在c.Next方法前后分别记录时间,就可以得出耗时。

有了自定义的中间件,我们就可以这么使用。

func main() {r := gin.New()r.Use(costTime())r.GET("/", func(c *gin.Context) {c.JSON(200, "首页")})r.Run(":8080")
}

现在启动程序,在浏览器里打开就可以看到如下日志信息了。

the request URL / cost 26.533µs

通过自定义中间件,我们可以很方便的拦截请求,来做一些我们需要做的事情,比如日志记录、授权校验、各种过滤等等。

责任链模式

在讲Gin的中间件的原理之前,我们先了解下设计模式中的责任链模式。顾名思义,责任链模式就是为请求创建一个对象链,对象链上的每个对象都可以依次对请求进行处理,并把处理过的请求传递给下一个对象。

看上图比较形象,从左到右横向是一个请求,在请求之上的是一个个对象(1-5),这5个对象就组成了处理责任链,依次对请求进行处理,并且处理完之后,把请求传递给下一个对象处理,生动描述详见下图:

剩余精彩核心原理部分请点击:

Golang Gin 实战(十三)| 中间件详解看这一篇就够了​mp.weixin.qq.com

精彩文章推荐

Golang Gin 实战(十二)| ProtoBuf 使用和源码分析原理实现

Golang Gin 实战(十一)| HTML模板渲染

Golang Gin 实战(十)| XML渲染

Golang Gin 实战(九)| JSONP跨域和劫持

Golang Gin 实战(八)| JSON渲染输出

我有几个的Go语言交流微信群,可以扫码关注公众号flysnow_org或者网站 https://www.flysnow.org/,加我好友,我拉你进来。

代理后台中间件_Golang Gin 实战(十三)| 中间件详解看这一篇就够了相关推荐

  1. JAVA 支付宝支付系统实战项目超详解

    结合支付宝官网实现的 支付宝当面支付功能,非常详细看我一篇就够了 1. 目的 2. 说明 3. 申请支付宝的账号(每个人都有做,不要用我的) 3.1. 扫码登陆 3.2. 账号的申请 3.3. 记录你 ...

  2. Elasticsearch实战——function_score 查询详解

    Elasticsearch实战--function_score 查询详解 文章目录 Elasticsearch实战--function_score 查询详解 1. function_score简介 2 ...

  3. HMI智能串口屏——在STM32开发板上的实战应用及其详解

    HMI智能串口屏--在STM32开发板上的实战应用及其详解 一.HMI智能串口屏使用步骤 二.附录 一.HMI智能串口屏使用步骤 安装USART HMI软件 (一般买的串口屏里面,商家送的资料里面都有 ...

  4. c++入门代码_Golang Gin 实战(一)| 快速安装入门

    Golang Gin 实战(一)| 快速安装入门 Gin 是一个非常优秀的Golang Web Framework,它不光API友好,性能也非常高,并且设计简洁,便于入门.所以它(Gin)非常受欢迎, ...

  5. html获取url后面的参数_Golang Gin 实战(四)| URL查询参数的获取和原理分析

    在 上一篇 Golang Gin 实战(三)| 路由参数 文章中,主要介绍了路由通配符.路由参数,让我们有了一种可以从URL路径中获取参数的方式,同时又不是重复的注册相似的路由. 这一篇,主要介绍查询 ...

  6. 中间件:ElasticSearch组件RestHighLevelClient用法详解

    本文源码:GitHub·点这里 || GitEE·点这里 一.基础API简介 1.RestHighLevelClient RestHighLevelClient的API作为ElasticSearch备 ...

  7. [Golang梦工厂]一个小项目带你学会GIN框架、JWT鉴权、swagger生成接口文档,看这一篇就够了

    前言 哈喽,大家好,我是asong,这是我的第八篇原创文章.听说你们还不会jwt.swagger,所以我带来一个入门级别的小项目.实现用户登陆.修改密码的操作.使用GIN(后台回复Golang梦工厂: ...

  8. java面试题,看我这篇就够了,前端后台应有尽有,包你通过面试

    面试题精华版:https://blog.csdn.net/cencong863251/article/details/88963573 以下为详情版: HTML&CSS部分 1.HTML中定义 ...

  9. docker 镜像修改的配置文件自动还原_Docker 基础与实战,看这一篇就够了

    作者 |  单一色调责编 | ElleDocker 基础 什么是Docker Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,names ...

最新文章

  1. getElementById 使用
  2. 判断远程文件是否存在
  3. Spark系列(八)Worker工作原理
  4. 深入理解JVM(8)——类加载的时机
  5. CPU乱序执行(指令重排序)
  6. uva 11584——Partitioning by Palindromes
  7. ubuntu 16.04 更改jupyter notebook工作路径
  8. 博文内部设置目录尝试
  9. JAVA实现Word转Pdf文件
  10. BT5中安装VMWare Tool的相关命令
  11. 迪恩素材教程资源图片下载站源码 dz社区论坛discuz 模板
  12. nosqlbooster pojie
  13. 好消息!这些城市个人手机、在家“刷脸”都能提取公积金,有你家吗?
  14. netty报错:LEAK: ByteBuf.release() was not called before it‘s garbage-collected
  15. matlab figure 虚线圆,flutter 画圆,虚线圆,渐变圆
  16. 2019年面试大概问题
  17. 详细前端面试题javascript篇--持续更新
  18. 潦草字体在线识别_连笔字在线生成器
  19. 【SemiDrive源码分析】【X9芯片启动流程】12 - freertos_safetyos目录Cortex-R5 DIL2.bin 之 sdm_display_init 显示初始化源码分析
  20. 稳定性全系列(二)——如何做线上全链路压测

热门文章

  1. Java:基于LinkedList实现栈和队列
  2. ASP.NET - JQuery的.getJSON给Dropdownlist绑定Item
  3. 使用DevExpress的WebChartControl控件绘制图表(柱状图、折线图、饼图)
  4. asp 文件上传 代码
  5. 陕西西咸新区暨沣渭新区泾渭新区网上截图!
  6. 【报告分享】2020海外留学趋势报告.pdf(附下载链接)
  7. 【报告分享】直播电商生态进化论-2020直播电商行业研究报告.pdf(附下载链接)...
  8. tmux鼠标操作配置
  9. C++将double类型小数以16进制格式打印出
  10. 蓝桥杯 算法训练 Sticks