Skip to content

Commit d9d3b75

Browse files
author
zhangyi
committed
Bug fix:
- fatal error: concurrent map writes(gin-contrib#15)
1 parent c7b2e17 commit d9d3b75

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

timeout.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,11 @@ func New(opts ...Option) gin.HandlerFunc {
8585
tw.FreeBuffer()
8686
bufPool.Put(buffer)
8787

88-
c.Writer = w
89-
t.response(c)
90-
c.Writer = tw
88+
// Copy gin.Context here to avoid concurrent writes to c.ResponseWriter's header(which is a map),
89+
// see https://github.com/gin-contrib/timeout/issues/15
90+
ctxCopy := c.Copy()
91+
ctxCopy.Writer = w
92+
t.response(ctxCopy)
9193
}
9294
}
9395
}

timeout_test.go

+23
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,26 @@ func TestPanic(t *testing.T) {
100100
assert.Equal(t, http.StatusInternalServerError, w.Code)
101101
assert.Equal(t, "", w.Body.String())
102102
}
103+
104+
func TestConcurrentHeaderWrites(t *testing.T) {
105+
r := gin.New()
106+
r.Use(gin.Recovery())
107+
r.Use(New(
108+
WithTimeout(time.Millisecond*50),
109+
WithHandler(func(c *gin.Context) {
110+
c.Next()
111+
}),
112+
))
113+
r.GET("/", func(c *gin.Context) {
114+
for {
115+
c.Header("X-Foo", "bar")
116+
}
117+
})
118+
119+
w := httptest.NewRecorder()
120+
req, err := http.NewRequest(http.MethodGet, "/", nil)
121+
if err != nil {
122+
t.Fatal("http NewRequest: ", err)
123+
}
124+
r.ServeHTTP(w, req)
125+
}

0 commit comments

Comments
 (0)