response.go 3.2 KB

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