Mygin实现中间件Middleware
本篇是mygin的第六篇,参照gin框架,感兴趣的可以从 Mygin第一篇 开始看,Mygin从零开始完全手写,在实现的同时,带你一窥gin框架的核心原理实现。
目的
- 实现中间件Middleware
在上一篇 Mygin实现分组路由Group 中,实现了路由分组,且同一分组的执行,会先执行Group,有一点点中间件的雏形了。但是中间件不完全还应该提供中断功能,比如一个Group组中添加了auth鉴权中间件,只有auth认证通过才可以通过,因此需要对上篇中的内容进行一些修改。
在实现之前,先分析gin中是怎样去实现的这一功能的
func (c *Context) Next() {
c.index++
//遍历handlers
for c.index < int8(len(c.handlers)) {
//真正调用执行handler方法
c.handlers[c.index](c)
c.index++
}
}
这个时候就有疑问了,从上述方法中看不到中间件执行失败的中断方法,那又是怎么实现中断。
在揭晓答案之前,先看看int8(len(c.handlers) 为什么要写个int8,原因在于gin中规定的handlers最多63个,相信实际的应用请求中,没有超过63个那么多变态的执行链。在gin中如果某一中间件执行失败,就把c.index赋值为63,上述for循环就不满足条件,因此就跳出for循环,不再继续执行后面的代码。gin中对应的代码也很简单。
const abortIndex int8 = math.MaxInt8 >> 1
//中间件执行失败,中断方法
func (c *Context) Abort() {
c.index = abortIndex
}
因此只需在mygin/content.go中新加Next方法和Abort方法
上下文
content.go中的代码不多,索性加上注释全部贴出来。
- mygin/content.go
package mygin
import (
"encoding/json"
"math"
"net/http"
)
// 定义 表示最大和上下文应中止时的索引值
const abortIndex int8 = math.MaxInt8 >> 1
// Context 封装了一个HTTP请求的上下文
type Context struct {
Request *http.Request
Writer http.ResponseWriter
Params Params
index int8
}
// Next 执行链中的剩余处理程序。
func (c *Context) Next(handlers HandlersChain) {
//遍历handlers
for c.index < int8(len(handlers)) {
//真正调用执行handler方法
handlers[c.index](c)
c.index++
}
}
// Abort 中断链中剩余处理程序的执行。
func (c *Context) Abort() {
c.index = abortIndex
}
// IsAborted 如果当前上下文被中止,则返回true。
func (c *Context) IsAborted() bool {
return c.index >= abortIndex
}
// writeContentType 如果尚未设置,则设置Content-Type标头。
func writeContentType(w http.ResponseWriter, value []string) {
header := w.Header()
if val := header["Content-Type"]; len(val) == 0 {
header["Content-Type"] = value
}
}
// Status 设置HTTP响应状态码。
func (c *Context) Status(code int) {
c.Writer.WriteHeader(code)
}
// JSON 将值序列化为JSON并将其写入响应。
func (c *Context) JSON(v interface{}) error {
writeContentType(c.Writer, []string{"application/json; charset=utf-8"})
encoder := json.NewEncoder(c.Writer)
err := encoder.Encode(v)
if err != nil {
c.Status(http.StatusInternalServerError)
}
c.Status(http.StatusOK)
return err
}
// Html 将字符串以HTML形式写入响应。
func (c *Context) Html(v string) error {
writeContentType(c.Writer, []string{"text/html; charset=utf-8"})
c.Status(http.StatusOK)
_, err := c.Writer.Write([]byte(v))
return err
}
// String 将字符串写入响应
func (c *Context) String(v string) error {
writeContentType(c.Writer, []string{"text/plain; charset=utf-8"})
c.Status(http.StatusOK)
_, err := c.Writer.Write([]byte(v))
return err
}
接下来就是调用handles的修改了,原来的解决方法是直接循环调用,对应的代码如下:
for _, handler := range handlers {
handler(&Context{
Request: r,
Writer: w,
Params: params,
})
}
引擎
- mygin/engine.go
现在找到engine.go文件中将上面的代码替换为:
//实例化一个下上文
c := &Context{
Request: r,
Writer: w,
Params: params,
}
// 执行处理函数链
c.Next(handlers)
测试代码
package main
import (
"gophp/mygin"
"path"
)
func main() {
// 创建一个默认的 mygin 实例
r := mygin.Default()
//测试Abort
group := r.Group("/api", func(context *mygin.Context) {
//todo....
context.String("api Group 中间件失败了....\n")
context.Abort()
})
//这个回调不会执行
group.GET("/hello/:name", func(context *mygin.Context) {
name := context.Params.ByName("name")
context.String(path.Join("hello ", name, "!"))
})
//测试没有发生Abort
group2 := r.Group("/api2", func(context *mygin.Context) {
//todo....
context.String("api Group 中间件成功了....\n")
})
//这个回调会执行
group2.GET("/hello2/:name", func(context *mygin.Context) {
name := context.Params.ByName("name")
context.String(path.Join("hello2 ", name, "!\n"))
})
// 启动服务器并监听端口
r.Run(":8088")
}
curl测试
curl http://127.0.0.1:8088/api/hello/scott
api Group 中间件失败了....
~ curl http://127.0.0.1:8088/api2/hello2/scott
api Group 中间件成功了....
hello2 /scott/!
看到上诉输出,即为成功。
Mygin实现中间件Middleware的更多相关文章
- ASP.NET Core 开发-中间件(Middleware)
ASP.NET Core开发,开发并使用中间件(Middleware). 中间件是被组装成一个应用程序管道来处理请求和响应的软件组件. 每个组件选择是否传递给管道中的下一个组件的请求,并能之前和下一组 ...
- ASP.NET Core中间件(Middleware)实现WCF SOAP服务端解析
ASP.NET Core中间件(Middleware)进阶学习实现SOAP 解析. 本篇将介绍实现ASP.NET Core SOAP服务端解析,而不是ASP.NET Core整个WCF host. 因 ...
- laravel中间件-----------middleware
middleware中间件 是访问到达服务器后在被对应的路由处理之前所经过的一层过滤层,故称中间件. 中间件是存放在app\http\middleware中,需要定一个 handle 处理方法,在ha ...
- 二、中间件(middleware)
1. 中间件(middleware) Django中的中间件主要实现一些附加功能,在request被用户handler处理前,以及用户handler处理后生存的response进行处理.因此 ...
- 中间件(Middleware)
中间件(Middleware) ASP.NET Core开发,开发并使用中间件(Middleware). 中间件是被组装成一个应用程序管道来处理请求和响应的软件组件. 每个组件选择是否传递给管道中的下 ...
- 初探中间件(middleware)
初探中间件(middleware) 因为考虑到文章的长度, 所以 BaseHandler 的展开被推迟了. 在 BaseHandler 中隐藏着中间件的信息, 较常见的 SessionMiddlewa ...
- django中间件Middleware
熟悉web开发的同学对hook钩子肯定不陌生,通过钩子可以方便的实现一些触发和回调,并且做一些过滤和拦截. django中的中间件(middleware)就是类似钩子的一种存在.下面我们来介绍一下,并 ...
- 如何传递参数给ASP.NET Core的中间件(Middleware)
问题描述 当我们在ASP.NET Core中定义和使用中间件(Middleware)的时候,有什么好的办法可以给中间件传参数吗? 解决方案 在ASP.NET Core项目中添加一个POCO类来传递参数 ...
- ASP.NET Core -中间件(Middleware)使用
ASP.NET Core开发,开发并使用中间件(Middleware). 中间件是被组装成一个应用程序管道来处理请求和响应的软件组件. 每个组件选择是否传递给管道中的下一个组件的请求,并能之前和下一组 ...
- C# Owin 创建与测试自己的中间件Middleware(二)
本文纯属介绍怎么简单地创建自己的Owin.还没有理解owin概念的请看上一篇文章:http://www.cnblogs.com/alunchen/p/7049307.html 目录 1.创建项目 2. ...
随机推荐
- Appium常用定位方法讲解
Appium常用定位方法讲解 对象定位是自动化测试中很关键的一步,也可以说是 最关键的一步,毕竟你对象都没定位那么你想操作也不行,下面我们来看常用的一些定位方式. ID定位(取resource-id的 ...
- Mysql--表注释,字段注释
information_schema数据库是MySQL数据库自带的数据库,里面存放的MySQL数据库所有的信息,包括数据表.数据注释.数据表的索引.数据库的权限等等. 1.添加表.字段注释 creat ...
- VSCode一键调用DOSBox运行MASM/TASM代码的自定义任务
在学习汇编的时候,发现很多教程都未使用 VSC 进行开发,今天在 Gitee 看有意思的项目时候发现了这个 DOS汇编/VSC-ASMtasks 通过配置VSCode的自定义任务来实现调用dosbox ...
- 《机器学习实战》 | 第3章 决策树(含Matplotlib模块介绍)
系列文章:<机器学习实战>学习笔记 本篇文章使用到的完整代码:Here 决策树 优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据. 缺点:可能会产生过度 ...
- Latex公式排版问题总结
Latex写博客和论文,因为有模板,所以用起来还是很方便的. 但是在实际使用中,由于论文是双栏的,因此比较长的公式在排版时会比较困难.下面对Latex中的公式排版方法做一些记录. Latex公式排版( ...
- 【内核】深入分析内核panic(三)--内核错误处理流程
1 内核错误处理方式 当内核出现致命错误时,只要cpu还能正常运行,那么最重要的就是向用户输出详细的错误信息,以及保存问题出现时的错误现场.以上致命错误可包含以下两种类型: (1)硬件能检测到的错误, ...
- 《深入理解计算机系统》实验五 —— Perfom Lab
本次实验是CSAPP的第5个实验,这次实验主要是让我们熟悉如何优化程序,如何写出更具有效率的代码.通过这次实验,我们可以更好的理解计算机的工作原理,在以后编写代码时,具有能结合软硬件思考的能力. @ ...
- 请问Sass/SCSS(with node-sass)和Sass/SCSS(with dart-sass)选哪个?
node-sass是自动编译实时的,dart-sass需要保存后才会生效. 如果您在Dart-VM内运行Dart-Sass,它的运行速度很快,但它表示可以编译为纯JS,dart-sass只是一个编译版 ...
- Node版本升级和降级
https://blog.csdn.net/qq_29262849/article/details/52973095
- TortoiseSVN 中文手册下载
TortoiseSVN 链接:https://pan.baidu.com/s/1wAxZST9wKc_HebOrBiewjw 提取码:3gjq