Files
b0esche_cloud/go_cloud/internal/errors/errors.go
2025-12-18 00:11:30 +01:00

74 lines
1.8 KiB
Go

package errors
import (
"encoding/json"
"fmt"
"net/http"
"os"
"github.com/go-chi/chi/v5/middleware"
"github.com/google/uuid"
)
// ErrorCode represents standardized error codes
type ErrorCode string
const (
CodeUnauthenticated ErrorCode = "UNAUTHENTICATED"
CodePermissionDenied ErrorCode = "PERMISSION_DENIED"
CodeNotFound ErrorCode = "NOT_FOUND"
CodeConflict ErrorCode = "CONFLICT"
CodeInvalidArgument ErrorCode = "INVALID_ARGUMENT"
CodeInternal ErrorCode = "INTERNAL"
)
// ErrorResponse represents the JSON error response structure
type ErrorResponse struct {
Code ErrorCode `json:"code"`
Message string `json:"message"`
}
// WriteError writes a standardized JSON error response
func WriteError(w http.ResponseWriter, code ErrorCode, message string, status int) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
json.NewEncoder(w).Encode(ErrorResponse{
Code: code,
Message: message,
})
}
// GetRequestID extracts the request ID from the request context
func GetRequestID(r *http.Request) string {
if reqID := middleware.GetReqID(r.Context()); reqID != "" {
return reqID
}
return "unknown"
}
// GetUserID extracts user ID from context if available
func GetUserID(r *http.Request) string {
if userID := r.Context().Value("user"); userID != nil {
if uid, ok := userID.(string); ok {
return uid
}
}
return ""
}
// GetOrgID extracts org ID from context if available
func GetOrgID(r *http.Request) string {
if orgID := r.Context().Value("org"); orgID != nil {
if oid, ok := orgID.(uuid.UUID); ok {
return oid.String()
}
}
return ""
}
// LogError logs an error with context
func LogError(r *http.Request, err error, message string) {
fmt.Fprintf(os.Stderr, "[ERROR] req_id=%s user_id=%s org_id=%s %s: %v\n",
GetRequestID(r), GetUserID(r), GetOrgID(r), message, err)
}