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。

相关推荐
callJJ13 小时前
Volta + Claude Code 在 Windows 上的路径 Bug 复盘
windows·bug
RH23121113 小时前
2026.6.8Linux
java·数据库·中间件
xsc-xyc18 小时前
记一次RK3568搭建NAS BUG:开发板插上 USB 移动硬盘没反应
bug
理人综艺好会1 天前
双Token机制在实际项目中的应用与实践
中间件·token
番茄去哪了2 天前
神领物流面试题(一)
java·大数据·中间件
念何架构之路2 天前
消息中间件
中间件
都说名字长不会被发现2 天前
Spring Boot Starter 中间件账号密码加密方案设计与实现
java·spring boot·后端·中间件
瀚高PG实验室2 天前
java中间件无法连接数据库
java·数据库·中间件·瀚高数据库
放风铃的兔子3 天前
我把 5 个 Python bug 投进 CubeSandbox 当沙盘 —— 从 envd 协议反编译到一键 RED→GREEN
bug·issue
zh_xuan3 天前
诡异Bug:输入框删除字符,却越删越多
android·bug