feat(api): wrap JSON responses in envelope

Add response envelope middleware to standardize JSON responses as
`{code,data,message}` with consistent business codes across endpoints.
Update Swagger annotations and tests to reflect the new response shape.

BREAKING CHANGE: API responses are now wrapped in a response envelope; clients must read payloads from `data` and handle `code`/`message` fields.
This commit is contained in:
zenfun
2026-01-10 00:15:08 +08:00
parent f400ffde95
commit 33838b1e2c
40 changed files with 771 additions and 371 deletions

View File

@@ -1,13 +1,13 @@
package api
import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"github.com/alicebob/miniredis/v2"
"github.com/ez-api/ez-api/internal/middleware"
"github.com/ez-api/ez-api/internal/model"
"github.com/ez-api/ez-api/internal/service"
"github.com/gin-gonic/gin"
@@ -83,6 +83,7 @@ func TestMasterStats_AggregatesByKeyAndModel(t *testing.T) {
}
r := gin.New()
r.Use(middleware.ResponseEnvelope())
r.GET("/v1/stats", withMaster(h.GetSelfStats))
req := httptest.NewRequest(http.MethodGet, "/v1/stats?period=all", nil)
@@ -93,9 +94,7 @@ func TestMasterStats_AggregatesByKeyAndModel(t *testing.T) {
t.Fatalf("expected 200, got %d body=%s", rr.Code, rr.Body.String())
}
var resp MasterUsageStatsResponse
if err := json.Unmarshal(rr.Body.Bytes(), &resp); err != nil {
t.Fatalf("unmarshal: %v", err)
}
decodeEnvelope(t, rr, &resp)
if resp.TotalRequests != 2 || resp.TotalTokens != 17 {
t.Fatalf("unexpected totals: %+v", resp)
}
@@ -168,6 +167,7 @@ func TestAdminStats_AggregatesByProvider(t *testing.T) {
adminHandler := NewAdminHandler(db, db, masterSvc, syncSvc, statsSvc, nil)
r := gin.New()
r.Use(middleware.ResponseEnvelope())
r.GET("/admin/stats", adminHandler.GetAdminStats)
req := httptest.NewRequest(http.MethodGet, "/admin/stats?period=all", nil)
@@ -178,9 +178,7 @@ func TestAdminStats_AggregatesByProvider(t *testing.T) {
t.Fatalf("expected 200, got %d body=%s", rr.Code, rr.Body.String())
}
var resp AdminUsageStatsResponse
if err := json.Unmarshal(rr.Body.Bytes(), &resp); err != nil {
t.Fatalf("unmarshal: %v", err)
}
decodeEnvelope(t, rr, &resp)
if resp.TotalMasters != 2 || resp.ActiveMasters != 1 {
t.Fatalf("unexpected master counts: %+v", resp)
}