response.go 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package common
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "log"
  7. "log/slog"
  8. "net/http"
  9. "reflect"
  10. "runtime/debug"
  11. )
  12. import (
  13. "github.com/gin-gonic/gin"
  14. "github.com/go-playground/validator/v10"
  15. "google.golang.org/protobuf/encoding/protojson"
  16. "google.golang.org/protobuf/proto"
  17. "google.golang.org/protobuf/types/known/anypb"
  18. "gorm.io/gorm"
  19. )
  20. import (
  21. "auth-server/rpc_idl/dr_basic_pb"
  22. )
  23. func HttpSuccess(c *gin.Context, data ...interface{}) {
  24. if len(data) > 0 {
  25. if m, ok := data[0].(proto.Message); ok {
  26. success := OK.Translator(GetTrans(c.GetHeader("Language")))
  27. data, _ := anypb.New(m)
  28. resp := dr_basic_pb.HttpResponse{
  29. Code: success.Code,
  30. Description: string(success.Description),
  31. Solution: success.Solution,
  32. Data: data,
  33. }
  34. fullMarshalOptions := protojson.MarshalOptions{
  35. EmitUnpopulated: true,
  36. UseProtoNames: true,
  37. UseEnumNumbers: false,
  38. Indent: "",
  39. }
  40. fullJSON, err := fullMarshalOptions.Marshal(&resp)
  41. if err != nil {
  42. log.Fatalf("Failed to marshal with EmitUnpopulated: %v", err)
  43. }
  44. c.Status(http.StatusOK)
  45. c.Header("Content-Type", "application/json; charset=utf-8")
  46. c.Writer.WriteHeaderNow()
  47. if _, err := c.Writer.Write(fullJSON); err != nil {
  48. _ = c.Error(err)
  49. c.Abort()
  50. }
  51. } else {
  52. c.JSON(http.StatusOK, OK.Translator(GetTrans(c.GetHeader("Language"))).H(data[0]))
  53. }
  54. } else {
  55. c.JSON(http.StatusOK, OK.H())
  56. }
  57. }
  58. func ErrToH(err interface{}, locale string) gin.H {
  59. h := gin.H{}
  60. switch err.(type) {
  61. case *ResStatus:
  62. h = err.(*ResStatus).Translator(GetTrans(locale)).H()
  63. case *json.UnmarshalTypeError:
  64. utErr := err.(*json.UnmarshalTypeError)
  65. h = InvalidParam.Desc(FieldTypeError).SetParam(utErr.Field, utErr.Type.String()).Translator(GetTrans(locale)).H()
  66. case validator.ValidationErrors:
  67. for _, fieldError := range err.(validator.ValidationErrors) {
  68. return InvalidParam.Desc(ResDesc(fieldError.Error())).Translator(GetTrans(locale)).H()
  69. }
  70. default:
  71. if fmt.Sprintf("%v", err) == "EOF" {
  72. return InvalidParam.Desc("empty body").Translator(GetTrans(locale)).H()
  73. }
  74. if fmt.Sprintf("%v", err) == "unexpected EOF" {
  75. return InvalidParam.Desc("body must be in json format").Translator(GetTrans(locale)).H()
  76. }
  77. if errors.Is(err.(error), gorm.ErrRecordNotFound) {
  78. return NotExists.Translator(GetTrans(locale)).H()
  79. }
  80. slog.Error("uncaught error occurred", "type", reflect.TypeOf(err), "err", err, "stack", string(debug.Stack()))
  81. h = Unknown.Desc(ResDesc(fmt.Sprintf("%v", err))).Translator(GetTrans(locale)).H()
  82. }
  83. return h
  84. }
  85. func HttpErr(c *gin.Context, err interface{}) {
  86. h := ErrToH(err, c.GetHeader("Language"))
  87. slog.Warn("http err response", "method", c.Request.Method, "uri", c.Request.RequestURI, "msg", h)
  88. c.JSON(http.StatusOK, h)
  89. }