From a2a45467de7d98f73f676a3eeba4b7c4a5b50bdf Mon Sep 17 00:00:00 2001 From: vierblatt <1846067379@qq.com> Date: Sun, 5 Jul 2026 02:23:51 +0800 Subject: [PATCH] feat(context): warn on multiple response writes Adds a debug-mode warning in Context.Render() when the response body has already been written. This matches the existing warning pattern in response_writer.go for duplicate header writes. Fixes #4477 --- context.go | 4 ++++ middleware_test.go | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/context.go b/context.go index 1dc730e3..defd7aad 100644 --- a/context.go +++ b/context.go @@ -1208,6 +1208,10 @@ func (c *Context) Render(code int, r render.Render) { return } + if c.Writer.Written() { + debugPrint("[WARNING] Response body has already been written. Wanted to override response.") + } + if err := r.Render(c.Writer); err != nil { // Pushing error to c.Errors _ = c.Error(err) diff --git a/middleware_test.go b/middleware_test.go index 8dc7c3b3..7f6ba9c4 100644 --- a/middleware_test.go +++ b/middleware_test.go @@ -251,3 +251,16 @@ func TestMiddlewareWrite(t *testing.T) { assert.Equal(t, http.StatusBadRequest, w.Code) assert.Equal(t, strings.ReplaceAll("hola\nbar{\"foo\":\"bar\"}{\"foo\":\"bar\"}event:test\ndata:message\n\n", " ", ""), strings.ReplaceAll(w.Body.String(), " ", "")) } + +func TestMultipleResponseWritesWarning(t *testing.T) { + router := New() + router.GET("/", func(c *Context) { + c.String(http.StatusOK, "first\n") + c.String(http.StatusOK, "second\n") + }) + + w := PerformRequest(router, http.MethodGet, "/") + + assert.Equal(t, http.StatusOK, w.Code) + assert.Equal(t, "first\nsecond\n", w.Body.String()) +}