response.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // Package response provides the unified response envelope {code, message, data}
  2. // returned by every endpoint of this service.
  3. package response
  4. import (
  5. "context"
  6. "errors"
  7. "net/http"
  8. "strings"
  9. "udeServer/internal/apierr"
  10. "github.com/zeromicro/go-zero/rest/httpx"
  11. )
  12. // Business codes carried in the unified response body.
  13. const (
  14. CodeOK = 100000
  15. CodeBadRequest = 100001
  16. CodeNotFound = 100002
  17. CodeServerError = 100003
  18. )
  19. // MsgOK is the message of every successful response.
  20. const MsgOK = "操作成功"
  21. // Body is the unified response envelope.
  22. type Body struct {
  23. Code int `json:"code"`
  24. Message string `json:"message"`
  25. Data any `json:"data"`
  26. }
  27. // OK builds a successful response body.
  28. func OK(data any) Body {
  29. return Body{Code: CodeOK, Message: MsgOK, Data: data}
  30. }
  31. // Register installs the global success and error handlers on the framework,
  32. // so every endpoint response is wrapped in the unified envelope:
  33. // - success: HTTP 200 + {"code":100000,...,"data":<resp>}
  34. // - failure: HTTP 200 + {"code":100xxx,...,"data":null}
  35. func Register() {
  36. httpx.SetOkHandler(func(_ context.Context, data any) any {
  37. return OK(data)
  38. })
  39. // HTTP status is always 200; the client decides by body code only.
  40. httpx.SetErrorHandler(func(err error) (int, any) {
  41. return http.StatusOK, Body{
  42. Code: Code(err),
  43. Message: err.Error(),
  44. Data: nil,
  45. }
  46. })
  47. }
  48. // Code maps an error to its business code. Errors without an HTTP-aware
  49. // status, e.g. failures from the framework request parser, fall back to
  50. // CodeServerError unless they describe a missing/unset field.
  51. func Code(err error) int {
  52. var apiErr *apierr.Error
  53. if errors.As(err, &apiErr) {
  54. return statusToCode(apiErr.Status)
  55. }
  56. // The request parser reports missing required fields as a plain error
  57. // like `field "name" is not set` (core/mapping/unmarshaler.go), which is
  58. // a client-side problem rather than a server error.
  59. if strings.HasSuffix(err.Error(), " is not set") {
  60. return CodeBadRequest
  61. }
  62. return CodeServerError
  63. }
  64. // statusToCode maps the HTTP-aware status of apierr.Error to the body code.
  65. func statusToCode(status int) int {
  66. switch status {
  67. case http.StatusBadRequest:
  68. return CodeBadRequest
  69. case http.StatusNotFound:
  70. return CodeNotFound
  71. default:
  72. return CodeServerError
  73. }
  74. }