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

@@ -167,8 +167,8 @@ func (h *MasterHandler) masterLogBase(masterID uint) (*gorm.DB, error) {
// @Param group query string false "route group"
// @Param model query string false "model"
// @Param status_code query int false "status code"
// @Success 200 {object} ListLogsResponse
// @Failure 500 {object} gin.H
// @Success 200 {object} ResponseEnvelope{data=ListLogsResponse}
// @Failure 500 {object} ResponseEnvelope{data=gin.H}
// @Router /admin/logs [get]
func (h *Handler) ListLogs(c *gin.Context) {
limit, offset := parseLimitOffset(c)
@@ -267,9 +267,9 @@ type DeleteLogsResponse struct {
// @Produce json
// @Security AdminAuth
// @Param request body DeleteLogsRequest true "Delete filters"
// @Success 200 {object} DeleteLogsResponse
// @Failure 400 {object} gin.H
// @Failure 500 {object} gin.H
// @Success 200 {object} ResponseEnvelope{data=DeleteLogsResponse}
// @Failure 400 {object} ResponseEnvelope{data=gin.H}
// @Failure 500 {object} ResponseEnvelope{data=gin.H}
// @Router /admin/logs [delete]
func (h *Handler) DeleteLogs(c *gin.Context) {
var req DeleteLogsRequest
@@ -357,10 +357,10 @@ func (h *Handler) deleteLogsBefore(cutoff time.Time, keyID uint, modelName strin
// @Param since query int false "unix seconds"
// @Param until query int false "unix seconds"
// @Param group_by query string false "group by dimension: model, day, month, hour, minute. Returns GroupedStatsResponse when specified." Enums(model, day, month, hour, minute)
// @Success 200 {object} LogStatsResponse "Default aggregated stats (when group_by is not specified)"
// @Success 200 {object} GroupedStatsResponse "Grouped stats (when group_by is specified)"
// @Failure 400 {object} gin.H
// @Failure 500 {object} gin.H
// @Success 200 {object} ResponseEnvelope{data=LogStatsResponse} "Default aggregated stats (when group_by is not specified)"
// @Success 200 {object} ResponseEnvelope{data=GroupedStatsResponse} "Grouped stats (when group_by is specified)"
// @Failure 400 {object} ResponseEnvelope{data=gin.H}
// @Failure 500 {object} ResponseEnvelope{data=gin.H}
// @Router /admin/logs/stats [get]
func (h *Handler) LogStats(c *gin.Context) {
q := h.logBaseQuery()
@@ -767,9 +767,9 @@ func buildTrafficChartSeriesResponse(rows []trafficBucketRow, topN int, granular
// @Param since query int false "Start time (unix seconds), defaults to 24h ago"
// @Param until query int false "End time (unix seconds), defaults to now"
// @Param top_n query int false "Number of top models to return (1-20), defaults to 5"
// @Success 200 {object} TrafficChartResponse
// @Failure 400 {object} gin.H
// @Failure 500 {object} gin.H
// @Success 200 {object} ResponseEnvelope{data=TrafficChartResponse}
// @Failure 400 {object} ResponseEnvelope{data=gin.H}
// @Failure 500 {object} ResponseEnvelope{data=gin.H}
// @Router /admin/logs/stats/traffic-chart [get]
func (h *Handler) GetTrafficChart(c *gin.Context) {
// Parse granularity
@@ -869,9 +869,9 @@ func (h *Handler) GetTrafficChart(c *gin.Context) {
// @Param until query int false "unix seconds"
// @Param model query string false "model"
// @Param status_code query int false "status code"
// @Success 200 {object} ListMasterLogsResponse
// @Failure 401 {object} gin.H
// @Failure 500 {object} gin.H
// @Success 200 {object} ResponseEnvelope{data=ListMasterLogsResponse}
// @Failure 401 {object} ResponseEnvelope{data=gin.H}
// @Failure 500 {object} ResponseEnvelope{data=gin.H}
// @Router /v1/logs [get]
func (h *MasterHandler) ListSelfLogs(c *gin.Context) {
master, exists := c.Get("master")
@@ -928,9 +928,9 @@ func (h *MasterHandler) ListSelfLogs(c *gin.Context) {
// @Security MasterAuth
// @Param since query int false "unix seconds"
// @Param until query int false "unix seconds"
// @Success 200 {object} LogStatsResponse
// @Failure 401 {object} gin.H
// @Failure 500 {object} gin.H
// @Success 200 {object} ResponseEnvelope{data=LogStatsResponse}
// @Failure 401 {object} ResponseEnvelope{data=gin.H}
// @Failure 500 {object} ResponseEnvelope{data=gin.H}
// @Router /v1/logs/stats [get]
func (h *MasterHandler) GetSelfLogStats(c *gin.Context) {
master, exists := c.Get("master")