fix: reduce default error response overhead

Encode the built-in 404 and 405 payload with a fixed struct instead of a map so default error pages allocate less on the hot miss path. Add a regression test to keep the JSON shape stable.
This commit is contained in:
wjqserver 2026-04-07 09:35:39 +08:00
parent 57847fa446
commit fa027347d3
2 changed files with 28 additions and 5 deletions

View file

@ -126,6 +126,12 @@ type ErrorHandler func(c *Context, code int, err error)
var errMethodNotAllowed = errors.New("method not allowed") var errMethodNotAllowed = errors.New("method not allowed")
var errNotFound = errors.New("not found") var errNotFound = errors.New("not found")
type defaultErrorResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Error string `json:"error"`
}
var methodNotAllowedHandler HandlerFunc = func(c *Context) { var methodNotAllowedHandler HandlerFunc = func(c *Context) {
httpMethod := c.Request.Method httpMethod := c.Request.Method
requestPath := routeLookupPath(c.Request) requestPath := routeLookupPath(c.Request)
@ -187,11 +193,7 @@ func defaultErrorHandle(c *Context, code int, err error) { // 检查客户端是
if err != nil { if err != nil {
errMsg = err.Error() errMsg = err.Error()
} }
c.JSON(code, H{ c.JSON(code, defaultErrorResponse{Code: code, Message: http.StatusText(code), Error: errMsg})
"code": code,
"message": http.StatusText(code),
"error": errMsg,
})
c.Writer.Flush() c.Writer.Flush()
c.Abort() c.Abort()
return return

View file

@ -1,6 +1,7 @@
package touka package touka
import ( import (
"encoding/json"
"net/http" "net/http"
"testing" "testing"
) )
@ -100,3 +101,23 @@ func TestOptionsAllowHeaderListsMatchingMethods(t *testing.T) {
t.Fatalf("expected Allow header to list matching methods, got %q", allow) t.Fatalf("expected Allow header to list matching methods, got %q", allow)
} }
} }
func TestDefaultErrorHandleJSONShape(t *testing.T) {
engine := New()
rr := PerformRequest(engine, http.MethodGet, "/missing", nil, nil)
if rr.Code != http.StatusNotFound {
t.Fatalf("expected status %d, got %d", http.StatusNotFound, rr.Code)
}
var body struct {
Code int `json:"code"`
Message string `json:"message"`
Error string `json:"error"`
}
if err := json.Unmarshal(rr.Body.Bytes(), &body); err != nil {
t.Fatalf("expected JSON error body, got %q: %v", rr.Body.String(), err)
}
if body.Code != http.StatusNotFound || body.Message != http.StatusText(http.StatusNotFound) || body.Error != "not found" {
t.Fatalf("unexpected error payload: %+v", body)
}
}