2026-05-19 11:00:28 +00:00
|
|
|
// Package response wraps handler output into the unified types.Status envelope.
|
|
|
|
|
// Logic layers should return (data, error) only; handlers call Write.
|
|
|
|
|
package response
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"net/http"
|
|
|
|
|
|
|
|
|
|
errs "gateway/internal/library/errors"
|
|
|
|
|
"gateway/internal/library/errors/code"
|
|
|
|
|
"gateway/internal/types"
|
|
|
|
|
|
|
|
|
|
"github.com/zeromicro/go-zero/rest/httpx"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Write serializes data or err into types.Status and writes the HTTP response.
|
2026-05-21 06:45:35 +00:00
|
|
|
// - Success: HTTP 200, code=102000, message=SUCCESS, data=<payload>
|
2026-05-19 11:00:28 +00:00
|
|
|
// - Failure: HTTP from errs.Error.HTTPStatus(), code/message/error from business error
|
|
|
|
|
func Write(ctx context.Context, w http.ResponseWriter, data any, err error) {
|
|
|
|
|
if err != nil {
|
|
|
|
|
status, body := buildError(err)
|
|
|
|
|
httpx.WriteJsonCtx(ctx, w, status, body)
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
httpx.WriteJsonCtx(ctx, w, http.StatusOK, buildOK(data))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func buildOK(data any) types.Status {
|
|
|
|
|
st := types.Status{
|
|
|
|
|
Code: code.DefaultSuccessFullCodeInt,
|
|
|
|
|
Message: code.DefaultSuccessMessage,
|
|
|
|
|
}
|
|
|
|
|
if data != nil {
|
|
|
|
|
st.Data = data
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return st
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func buildError(err error) (httpStatus int, body types.Status) {
|
|
|
|
|
if e := errs.FromError(err); e != nil {
|
|
|
|
|
return e.HTTPStatus(), types.Status{
|
|
|
|
|
Code: int64(e.Code()),
|
|
|
|
|
Message: e.Error(),
|
|
|
|
|
Error: types.ErrorDetail{
|
|
|
|
|
BizCode: e.DisplayCode(),
|
|
|
|
|
Scope: uint32(e.Scope()),
|
|
|
|
|
Category: uint32(e.Category()),
|
|
|
|
|
Detail: uint32(e.Detail()),
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Non-business errors: generic 500, do not leak internal error text to clients.
|
|
|
|
|
fallback := errs.MustNew(code.Unset, code.SysInternal, 0, "internal server error")
|
|
|
|
|
|
|
|
|
|
return fallback.HTTPStatus(), types.Status{
|
|
|
|
|
Code: int64(fallback.Code()),
|
|
|
|
|
Message: fallback.Error(),
|
|
|
|
|
Error: types.ErrorDetail{
|
|
|
|
|
BizCode: fallback.DisplayCode(),
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|