template-monorepo/internal/response/response.go

67 lines
1.7 KiB
Go
Raw Permalink Normal View History

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.
// - 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(),
},
}
}