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. ...
随机推荐
- 技术架构+应用场景揭秘,为什么高斯Redis比开源香?
摘要:高斯Redis即保留了开源Redis的能力,同时凭借其存算分离的架构,在成本.稳定性.可靠性.一致性等方面做出了新的突破,也更加适用于当下数据规模庞大的互联网业务. 本文分享自华为云社区< ...
- Chrome浏览器导出HTTPS证书
点证书小锁 进入证书界面 到详情中,导出证书
- Sublime Json 格式化
Ctrl+Shift+P 安装 pretty json Ctrl+Alt+J
- Java 事件链
Java中的事件机制的参与者有3种角色: 1. event object:就是事件产生时具体的"事件",用于listener的相应的方法之中,作为参数,一般存在于listerner ...
- 41. 干货系列从零用Rust编写负载均衡及代理,websocket与tcp的映射,WS与TCP互转
wmproxy wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,七层负载均衡,内网穿透,后续将实现websocket代 ...
- auth认证模块 auth_user表扩展
目录 auth认证模块前戏 django后台管理功能 创建超级管理员 auth认证相关模块及操作 用户注册 用户登录 网站首页效果 校验用户登录的装饰器 用户修改密码 用户注销登录 auth_user ...
- 用 three.js 绘制三维带箭头线 (线内箭头)
在LineMaterial.js基础上修改的ArrowLineMaterial.js代码: /** * @author WestLangley / http://github.com/WestLang ...
- px2vw一个px单位转成vw单位的VSCode插件
px2vw 一个 px 单位转成 vw 单位的 VSCode 插件
- C#查找算法1:二分查找
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法.但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列. 原理:将n个元素分成个数大致相同的两半,取 ...
- java基础-数组-day06
1. 引入数组 录入10个学生的成绩 求和 求平均 import java.util.Scanner; public class TestArray01{ public static void mai ...