Files
commerce/middleware/errorstatus_test.go
zeekay 1943f1c093 Hanzo Commerce
Multi-tenant commerce and billing: orders, subscriptions, invoices, plans,
usage metering and a credit ledger. One Go binary. MIT OR Apache-2.0.

Claude-Session: https://claude.ai/code/session_01SAtaDFm8VDiWrhYHNNtxMw
2026-09-23 21:52:16 -07:00

62 lines
2.0 KiB
Go

package middleware
import (
"net/http"
"testing"
"github.com/zap-proto/zip"
)
func do(t *testing.T, app *zip.App, target string) (*http.Response, string) {
t.Helper()
req, err := http.NewRequest("GET", target, nil)
if err != nil {
t.Fatal(err)
}
res, err := app.Test(req)
if err != nil {
t.Fatal(err)
}
b := make([]byte, 512)
n, _ := res.Body.Read(b)
_ = res.Body.Close()
return res, string(b[:n])
}
// A handler that returns an error has already said what it means: zip.ErrForbidden
// carries 403. The middleware must not flatten that to 500 — doing so is what made
// every unauthenticated /v1 read answer "server error" instead of "not allowed",
// and what let the status board show 12 broken services as green.
func TestReturnedErrorKeepsItsStatus(t *testing.T) {
app := zip.New(zip.Config{DisableStartupMessage: true})
// The route composes BENEATH the group whose middleware guards it. zip v1.23
// wraps a definition's own subtree rather than a URL prefix, so a route
// registered on the app merely SHARES the prefix — the handler would answer
// with the error middleware never having run. Composition says what wraps what.
store := app.Group("/v1/store")
store.Use(zip.H(ErrorHandlerJSON()))
store.Raw(http.MethodGet, "/x", func(c *zip.Ctx) error {
return zip.ErrForbidden("X-Org-Id required")
})
res, body := do(t, app, "/v1/store/x")
if res.StatusCode != 403 {
t.Fatalf("want 403, got %d: %s", res.StatusCode, body)
}
t.Logf("403 preserved: %s", body)
}
// A panic carries no status, so 500 is the honest answer and the process must live.
func TestPanicRecoversAs500(t *testing.T) {
app := zip.New(zip.Config{DisableStartupMessage: true})
store := app.Group("/v1/store")
store.Use(zip.H(ErrorHandlerJSON()))
store.Raw(http.MethodGet, "/boom", func(c *zip.Ctx) error { panic("boom") })
res, body := do(t, app, "/v1/store/boom")
if res.StatusCode != 500 {
t.Fatalf("want 500, got %d: %s", res.StatusCode, body)
}
t.Logf("panic recovered as 500: %s", body)
}