github.com/gin-contrib/timeout应前置使用

首先,gin的中间件是有执行顺序的,就是按照添加的顺序进行的。之前没在意,我把timeout中间件放在了最后面,导致业务一直不正常,后面debug源码总算看明白了:

源码入口:

go 复制代码
func(c *gin.Context) {
		finish := make(chan struct{}, 1)
		panicChan := make(chan interface{}, 1)

		w := c.Writer
		buffer := bufPool.Get()
		tw := NewWriter(w, buffer)
		c.Writer = tw
		buffer.Reset()
		.....
}

然后这个NewWriter(w, buffer)的实现如下:

go 复制代码
func NewWriter(w gin.ResponseWriter, buf *bytes.Buffer) *Writer {
	return &Writer{ResponseWriter: w, body: buf, headers: make(http.Header)}
}

他这里所做的就是把原始的writer下层一级,然后new了新的body和headers,也就是进行一层封装

这里也就意味着,假如你原来已经在body和header中写入了一些内容,在后续的代码中你就无法获取到原来的内容改了,获取到的是新的header 和body

当然,gin框架自带的中间件,肯定还是考虑得很细的,所以再最后他有把新旧header和body合并的操作:

go 复制代码
			dst := tw.ResponseWriter.Header()
			for k, vv := range tw.Header() {
				dst[k] = vv
			}

			if _, err := tw.ResponseWriter.Write(buffer.Bytes()); err != nil {
				panic(err)
			}

tw.Header()就是新header,dst就是旧header,用一个for循环新header中的值合并到旧header中,也就是原始的c *gin.Context中。这里一切看起来都那么的合理是吧!

但是,这里有个bug,假设在dst中,已经包含了keyabctw.Header()也有keyabc,那么旧的key就会被覆盖掉。导致原header信息丢失,这就是我项目中遇到的bug!

同理,body也是一样存在丢失的风险。

这里他就没考虑到这个问题,所以,该中间件需要放在有业务逻辑的中间件之前执行,这样才能避免出现这个bug。

相关推荐
Sagittarius_A*1 天前
Web 渗透实战:服务器系统识别、端口与中间件全量探测
服务器·网络安全·中间件·渗透测试
妙码生花2 天前
从 PHP 到 AI + Golang,程序员自救转型手记(三十三):权限规则管理器
后端·go·gin
李永奉2 天前
杰理可视化SDK开发-【BUG】配置“TWS两边同时按消息使能”功能后,按键单击功能无效失灵
开发语言·单片机·嵌入式硬件·物联网·bug
马里马里奥-2 天前
大模型应用开发笔记04:LangChain 工具(Tool)与中间件(Middleware)详解
笔记·中间件·langchain
AI大模型-小雄2 天前
充值Codex + GPT-5.5 并发 Bug 调试实战:从时序分析到回归测试
gpt·log4j·bug
霸道流氓气质2 天前
CDC 中间件捕获 Binlog 全流程详解
中间件
穷人小水滴3 天前
(科幻) 备用肉身虫 (Backup Body Bug, BBB) 系列设定 (202607 更新)
aigc·bug·科幻
名字还没想好☜4 天前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js
马里马里奥-4 天前
大模型应用开发笔记03:LangChain 中间件实战
笔记·中间件·langchain
heimeiyingwang5 天前
【架构实战】分库分表实战:ShardingSphere与中间件选型
中间件·架构