package httpapp import ( "log" "net/http" "gitea.avt.data-center.id/othman.suseno/atlas/internal/errors" ) // writeError writes a structured error response func writeError(w http.ResponseWriter, err error) { // Check if it's an APIError if apiErr, ok := err.(*errors.APIError); ok { writeJSON(w, apiErr.HTTPStatus, apiErr) return } // Default to internal server error log.Printf("unhandled error: %v", err) apiErr := errors.ErrInternal("an unexpected error occurred") writeJSON(w, apiErr.HTTPStatus, apiErr) } // handleServiceError handles errors from service operations with graceful degradation func (a *App) handleServiceError(serviceName string, err error) error { if err == nil { return nil } // Log the error for debugging log.Printf("%s service error: %v", serviceName, err) // For service errors, we might want to continue operation // but log the issue. The API request can still succeed // even if service configuration fails (desired state is stored) return errors.ErrServiceUnavailable(serviceName).WithDetails(err.Error()) } // recoverPanic recovers from panics and returns a proper error response func recoverPanic(w http.ResponseWriter, r *http.Request) { if rec := recover(); rec != nil { log.Printf("panic recovered: %v", rec) err := errors.ErrInternal("an unexpected error occurred") writeError(w, err) } } // errorMiddleware wraps handlers with panic recovery func (a *App) errorMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer recoverPanic(w, r) next.ServeHTTP(w, r) }) } // writeJSONError is a convenience function for JSON error responses func writeJSONError(w http.ResponseWriter, code int, message string) { writeJSON(w, code, map[string]string{"error": message}) }