package common import ( "encoding/json" "errors" "fmt" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "log" "log/slog" "net/http" "reflect" "runtime/debug" ) import ( "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" "gorm.io/gorm" ) import ( "auth-server/rpc_idl/dr_basic_pb" ) func HttpSuccess(c *gin.Context, data ...interface{}) { if len(data) > 0 { if m, ok := data[0].(proto.Message); ok { success := OK.Translator(GetTrans(c.GetHeader("Language"))) data, _ := anypb.New(m) resp := dr_basic_pb.HttpResponse{ Code: success.Code, Description: string(success.Description), Solution: success.Solution, Data: data, } fullMarshalOptions := protojson.MarshalOptions{ EmitUnpopulated: true, UseProtoNames: true, UseEnumNumbers: false, Indent: "", } fullJSON, err := fullMarshalOptions.Marshal(&resp) if err != nil { log.Fatalf("Failed to marshal with EmitUnpopulated: %v", err) } c.Status(http.StatusOK) c.Header("Content-Type", "application/json; charset=utf-8") c.Writer.WriteHeaderNow() if _, err := c.Writer.Write(fullJSON); err != nil { _ = c.Error(err) c.Abort() } } else { c.JSON(http.StatusOK, OK.Translator(GetTrans(c.GetHeader("Language"))).H(data[0])) } } else { c.JSON(http.StatusOK, OK.H()) } } func ErrToH(err interface{}, locale string) gin.H { h := gin.H{} switch err.(type) { case *ResStatus: h = err.(*ResStatus).Translator(GetTrans(locale)).H() case *json.UnmarshalTypeError: utErr := err.(*json.UnmarshalTypeError) h = InvalidParam.Desc(FieldTypeError).SetParam(utErr.Field, utErr.Type.String()).Translator(GetTrans(locale)).H() case validator.ValidationErrors: for _, fieldError := range err.(validator.ValidationErrors) { return InvalidParam.Desc(ResDesc(fieldError.Error())).Translator(GetTrans(locale)).H() } default: if fmt.Sprintf("%v", err) == "EOF" { return InvalidParam.Desc("empty body").Translator(GetTrans(locale)).H() } if fmt.Sprintf("%v", err) == "unexpected EOF" { return InvalidParam.Desc("body must be in json format").Translator(GetTrans(locale)).H() } if errors.Is(err.(error), gorm.ErrRecordNotFound) { return NotExists.Translator(GetTrans(locale)).H() } if st, ok := status.FromError(err.(error)); ok { switch st.Code() { case codes.NotFound: return NotExists.Desc(ResDesc(st.Message())).Translator(GetTrans(locale)).H() case codes.InvalidArgument: return InvalidParam.Desc(ResDesc(st.Message())).Translator(GetTrans(locale)).H() default: slog.Error("[rpc]Unrecognized grpc error", "err", err, "code", st.Code(), "msg", st.Message()) } } slog.Error("uncaught error occurred", "type", reflect.TypeOf(err), "err", err, "stack", string(debug.Stack())) h = Unknown.Desc(ResDesc(fmt.Sprintf("%v", err))).Translator(GetTrans(locale)).H() } return h } func HttpErr(c *gin.Context, err interface{}) { h := ErrToH(err, c.GetHeader("Language")) slog.Warn("http err response", "method", c.Request.Method, "uri", c.Request.RequestURI, "msg", h) c.JSON(http.StatusOK, h) }