// Package response provides the unified response envelope {code, message, data} // returned by every endpoint of this service. package response import ( "context" "errors" "net/http" "strings" "udeServer/internal/apierr" "github.com/zeromicro/go-zero/rest/httpx" ) // Business codes carried in the unified response body. const ( CodeOK = 100000 CodeBadRequest = 100001 CodeNotFound = 100002 CodeServerError = 100003 ) // MsgOK is the message of every successful response. const MsgOK = "操作成功" // Body is the unified response envelope. type Body struct { Code int `json:"code"` Message string `json:"message"` Data any `json:"data"` } // OK builds a successful response body. func OK(data any) Body { return Body{Code: CodeOK, Message: MsgOK, Data: data} } // Register installs the global success and error handlers on the framework, // so every endpoint response is wrapped in the unified envelope: // - success: HTTP 200 + {"code":100000,...,"data":} // - failure: HTTP 200 + {"code":100xxx,...,"data":null} func Register() { httpx.SetOkHandler(func(_ context.Context, data any) any { return OK(data) }) // HTTP status is always 200; the client decides by body code only. httpx.SetErrorHandler(func(err error) (int, any) { return http.StatusOK, Body{ Code: Code(err), Message: err.Error(), Data: nil, } }) } // Code maps an error to its business code. Errors without an HTTP-aware // status, e.g. failures from the framework request parser, fall back to // CodeServerError unless they describe a missing/unset field. func Code(err error) int { var apiErr *apierr.Error if errors.As(err, &apiErr) { return statusToCode(apiErr.Status) } // The request parser reports missing required fields as a plain error // like `field "name" is not set` (core/mapping/unmarshaler.go), which is // a client-side problem rather than a server error. if strings.HasSuffix(err.Error(), " is not set") { return CodeBadRequest } return CodeServerError } // statusToCode maps the HTTP-aware status of apierr.Error to the body code. func statusToCode(status int) int { switch status { case http.StatusBadRequest: return CodeBadRequest case http.StatusNotFound: return CodeNotFound default: return CodeServerError } }