Files
honeyDueAPI/internal/apperrors/handler.go
Trey t 4976eafc6c Rebrand from Casera/MyCrib to honeyDue
Total rebrand across all Go API source files:
- Go module path: casera-api -> honeydue-api
- All imports updated (130+ files)
- Docker: containers, images, networks renamed
- Email templates: support email, noreply, icon URL
- Domains: casera.app/mycrib.treytartt.com -> honeyDue.treytartt.com
- Bundle IDs: com.tt.casera -> com.tt.honeyDue
- IAP product IDs updated
- Landing page, admin panel, config defaults
- Seeds, CI workflows, Makefile, docs
- Database table names preserved (no migration needed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 06:33:38 -06:00

67 lines
2.0 KiB
Go

package apperrors
import (
"errors"
"fmt"
"net/http"
"github.com/go-playground/validator/v10"
"github.com/labstack/echo/v4"
"github.com/rs/zerolog/log"
"github.com/treytartt/honeydue-api/internal/dto/responses"
"github.com/treytartt/honeydue-api/internal/i18n"
customvalidator "github.com/treytartt/honeydue-api/internal/validator"
)
// HTTPErrorHandler handles all errors returned from handlers in a consistent way.
// It converts AppErrors, validation errors, and Echo HTTPErrors to JSON responses.
// This is the base handler - additional service-level error handling can be added in router.go.
func HTTPErrorHandler(err error, c echo.Context) {
// Already committed? Skip
if c.Response().Committed {
return
}
// Handle AppError (our custom application errors)
var appErr *AppError
if errors.As(err, &appErr) {
message := i18n.LocalizedMessage(c, appErr.MessageKey)
// If i18n key not found (returns the key itself), use fallback message
if message == appErr.MessageKey && appErr.Message != "" {
message = appErr.Message
} else if message == appErr.MessageKey {
message = appErr.MessageKey // Use the key as last resort
}
// Log internal errors
if appErr.Err != nil {
log.Error().Err(appErr.Err).Str("message_key", appErr.MessageKey).Msg("Application error")
}
c.JSON(appErr.Code, responses.ErrorResponse{Error: message})
return
}
// Handle validation errors from go-playground/validator
var validationErrs validator.ValidationErrors
if errors.As(err, &validationErrs) {
c.JSON(http.StatusBadRequest, customvalidator.FormatValidationErrors(err))
return
}
// Handle Echo's built-in HTTPError
var httpErr *echo.HTTPError
if errors.As(err, &httpErr) {
msg := fmt.Sprintf("%v", httpErr.Message)
c.JSON(httpErr.Code, responses.ErrorResponse{Error: msg})
return
}
// Default: Internal server error (don't expose error details to client)
log.Error().Err(err).Msg("Unhandled error")
c.JSON(http.StatusInternalServerError, responses.ErrorResponse{
Error: i18n.LocalizedMessage(c, "error.internal"),
})
}