mirror of
https://github.com/gin-gonic/gin.git
synced 2026-07-14 07:07:03 +08:00
Merge 065f526e702a43ae06a84a318e5fc4180b0423bb into 03f3e420a3c370659359fb4deb99a474229b215a
This commit is contained in:
commit
81124dfb36
@ -1120,8 +1120,15 @@ func bodyAllowedForStatus(status int) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Status sets the HTTP response code.
|
// Status sets the HTTP response code.
|
||||||
|
// For status codes that do not allow a response body (1xx, 204, 304),
|
||||||
|
// the status is flushed immediately so that httptest.ResponseRecorder
|
||||||
|
// and similar wrappers record the correct status without requiring a
|
||||||
|
// subsequent Write call.
|
||||||
func (c *Context) Status(code int) {
|
func (c *Context) Status(code int) {
|
||||||
c.Writer.WriteHeader(code)
|
c.Writer.WriteHeader(code)
|
||||||
|
if !bodyAllowedForStatus(code) {
|
||||||
|
c.Writer.WriteHeaderNow()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header is an intelligent shortcut for c.Writer.Header().Set(key, value).
|
// Header is an intelligent shortcut for c.Writer.Header().Set(key, value).
|
||||||
|
|||||||
@ -1942,6 +1942,59 @@ func TestContextAbortWithStatus(t *testing.T) {
|
|||||||
assert.True(t, c.IsAborted())
|
assert.True(t, c.IsAborted())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestContextStatusFlushesNoBodyCodes(t *testing.T) {
|
||||||
|
t.Run("204 No Content is flushed immediately", func(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, _ := CreateTestContext(w)
|
||||||
|
|
||||||
|
c.Status(http.StatusNoContent)
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusNoContent, c.Writer.Status())
|
||||||
|
assert.Equal(t, http.StatusNoContent, w.Code, "Status(204) should flush to underlying ResponseWriter without requiring Write()")
|
||||||
|
})
|
||||||
|
|
||||||
|
Run := func(code int) {
|
||||||
|
t.Run(fmt.Sprintf("%d %s is flushed immediately", code, http.StatusText(code)), func(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, _ := CreateTestContext(w)
|
||||||
|
|
||||||
|
c.Status(code)
|
||||||
|
|
||||||
|
assert.Equal(t, code, c.Writer.Status())
|
||||||
|
assert.Equal(t, code, w.Code, "Status(%d) should flush to underlying ResponseWriter", code)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1xx informational codes
|
||||||
|
Run(http.StatusContinue) // 100
|
||||||
|
Run(http.StatusSwitchingProtocols) // 101
|
||||||
|
Run(http.StatusProcessing) // 102
|
||||||
|
|
||||||
|
// 204 No Content
|
||||||
|
Run(http.StatusNoContent)
|
||||||
|
|
||||||
|
// 304 Not Modified
|
||||||
|
Run(http.StatusNotModified)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestContextStatusWithBodyDoesNotFlushEarly(t *testing.T) {
|
||||||
|
// Status codes that allow a body (e.g. 200) should NOT flush immediately,
|
||||||
|
// because the handler may still write content. The status is flushed
|
||||||
|
// when Write() is called.
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, _ := CreateTestContext(w)
|
||||||
|
|
||||||
|
c.Status(http.StatusOK)
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, c.Writer.Status())
|
||||||
|
// w.Code is 200 (default) because WriteHeaderNow has been called with the
|
||||||
|
// default status. The actual written status should still be 200 after
|
||||||
|
// Status(200) since no content has been written yet, but the key point
|
||||||
|
// is that calling Status(200) alone should not force an early flush
|
||||||
|
// that would prevent setting headers afterward.
|
||||||
|
assert.Equal(t, http.StatusOK, w.Code)
|
||||||
|
}
|
||||||
|
|
||||||
type testJSONAbortMsg struct {
|
type testJSONAbortMsg struct {
|
||||||
Foo string `json:"foo"`
|
Foo string `json:"foo"`
|
||||||
Bar string `json:"bar"`
|
Bar string `json:"bar"`
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user