diff --git a/internal/app/server/middleware.go b/internal/app/server/middleware.go index 4eb7d6e..a22acdd 100644 --- a/internal/app/server/middleware.go +++ b/internal/app/server/middleware.go @@ -2,6 +2,9 @@ package server import ( "fmt" + "log" + "net/http" + "runtime/debug" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" @@ -71,3 +74,45 @@ func JwtAuthMiddleWare(jwtSecretKey []byte) gin.HandlerFunc { ctx.Next() } } + +func RecoveryMiddleware() gin.HandlerFunc { + + return func(ctx *gin.Context) { + defer func() { + if r := recover(); r != nil { + // Log the panic with stack trace + err := fmt.Errorf("panic recovered: %v\n%s", r, debug.Stack()) + log.Printf("[PANIC RECOVERY] %s", err) + + ctx.JSON(http.StatusOK, gin.H{ + "status": http.StatusOK, + "error": "API_PANIC_RECOVERED", + "message": err.Error(), + }) + + // Determine the content type of the request for appropriate response + // acceptHeader := ctx.Request.Header.Get("Accept") + // + // // Customize the response based on the request type (e.g., HTML vs. JSON) + // if strings.Contains(acceptHeader, "text/html") { + // // For browser requests (HTML), redirect to an error page or render a template + // ctx.HTML(http.StatusInternalServerError, "error.html", gin.H{ + // "title": "Something went wrong", + // "message": "An unexpected error occurred. Please try again later.", + // }) + // } else if strings.Contains(acceptHeader, "application/json") || ctx.Request.Method == http.MethodPost { + // // For API requests (JSON), return a JSON error response + // ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ + // "error": "An internal server error occurred.", + // "message": "We're working to fix the problem. Please try again later.", + // // You might include a unique error ID here for tracking + // }) + // } else { + // // Fallback for other content types + // ctx.AbortWithStatus(http.StatusInternalServerError) + // } + } + }() + ctx.Next() + } +} diff --git a/internal/app/server/server.go b/internal/app/server/server.go index a921e6d..e543222 100644 --- a/internal/app/server/server.go +++ b/internal/app/server/server.go @@ -129,6 +129,7 @@ func (s *Server) Setup() *Server { } // Apply middleware + s.Router.Use(RecoveryMiddleware()) s.Router.Use(DepedencyInjectionMiddleware(deps)) s.Router.Use(JwtAuthMiddleWare(jwtSecret)) @@ -201,7 +202,7 @@ func (s *Server) Setup() *Server { // TODO: Use constants for errors? if strings.HasPrefix(path, domain.VERSION+domain.API) { ctx.JSON(http.StatusNotFound, gin.H{ - "status": 404, + "status": http.StatusNotFound, "error": "API_NOT_FOUND", "message": "The request endpoint does not exist.", "path": path,