-
Notifications
You must be signed in to change notification settings - Fork 8.6k
Add warning when writing response body multiple times (fixes #4477) #4483
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
8eb015d
dc128b7
4d32cf9
efdb77e
bc46a09
7b5727c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1158,6 +1158,15 @@ func (c *Context) Render(code int, r render.Render) { | |
| return | ||
| } | ||
|
|
||
| if c.Writer.Written() && IsDebugging() { | ||
| // Skip warning for SSE and streaming responses (status code -1) | ||
| if code != -1 { | ||
| if _, ok := r.(sse.Event); !ok { | ||
| debugPrint("[WARNING] Response body already written. Attempting to write again with status code %d", code) | ||
| } | ||
|
Comment on lines
+1161
to
+1166
|
||
| } | ||
| } | ||
|
|
||
| if err := r.Render(c.Writer); err != nil { | ||
| // Pushing error to c.Errors | ||
| _ = c.Error(err) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1424,6 +1424,43 @@ func TestContextRenderNoContentData(t *testing.T) { | |
| assert.Equal(t, "text/csv", w.Header().Get("Content-Type")) | ||
| } | ||
|
|
||
| // Test multiple JSON writes in debug mode | ||
| func TestContextRenderMultipleJSON(t *testing.T) { | ||
| w := httptest.NewRecorder() | ||
| c, _ := CreateTestContext(w) | ||
|
|
||
| oldMode := os.Getenv("GIN_MODE") | ||
| defer os.Setenv("GIN_MODE", oldMode) | ||
| SetMode(DebugMode) | ||
|
Comment on lines
+1432
to
+1434
|
||
|
|
||
|
Comment on lines
+1432
to
+1435
|
||
| output := captureOutput(t, func() { | ||
| c.JSON(http.StatusOK, H{"foo": "bar"}) | ||
| c.JSON(http.StatusOK, H{"baz": "qux"}) | ||
| }) | ||
|
|
||
| assert.Equal(t, http.StatusOK, w.Code) | ||
| assert.Contains(t, output, "[WARNING] Response body already written") | ||
| assert.Contains(t, output, "status code 200") | ||
| } | ||
|
|
||
| // Test multiple SSE writes in debug mode | ||
| func TestContextRenderMultipleSSE(t *testing.T) { | ||
| w := httptest.NewRecorder() | ||
| c, _ := CreateTestContext(w) | ||
|
|
||
| oldMode := os.Getenv("GIN_MODE") | ||
| defer os.Setenv("GIN_MODE", oldMode) | ||
| SetMode(DebugMode) | ||
|
Comment on lines
+1451
to
+1453
|
||
|
|
||
|
Comment on lines
+1451
to
+1454
|
||
| output := captureOutput(t, func() { | ||
| c.SSEvent("message", "test1") | ||
| c.SSEvent("message", "test2") | ||
| }) | ||
|
|
||
| assert.Equal(t, http.StatusOK, w.Code) | ||
| assert.NotContains(t, output, "[WARNING] Response body already written") | ||
| } | ||
|
|
||
| func TestContextRenderSSE(t *testing.T) { | ||
| w := httptest.NewRecorder() | ||
| c, _ := CreateTestContext(w) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The inline comment says “Skip warning for SSE and streaming responses (status code -1)”, but
code == -1is also used for non-streaming renders likerender.Redirect, and the logic also has a separatesse.Eventtype check. Please clarify the comment (and/or consolidate the conditions) so future readers understand why-1andsse.Eventare treated specially.