(FEAT): Added a handler to recover from panics.

This is not perfect, and def not set in stone. But for now, it will
return a JSON page, and not crash. I want this to log the user out,
clear the cookies, and then direct home with a message saying something
went wrong.

I also want it to send me an email with the details, but one step at a
time for now, that is not 100% necessary, I just need to fix the bugs.
I also need to fix the environments.
This commit is contained in:
Hayden Hargreaves 2025-07-22 22:11:11 -07:00
parent 65c73bddfa
commit 94740b4b54
2 changed files with 47 additions and 1 deletions

View File

@ -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()
}
}

View File

@ -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,