// steamcache/errors/errors.go package errors import ( "errors" "fmt" "net/http" ) // Common SteamCache errors var ( ErrInvalidURL = errors.New("steamcache: invalid URL") ErrUnsupportedService = errors.New("steamcache: unsupported service") ErrUpstreamUnavailable = errors.New("steamcache: upstream server unavailable") ErrCacheCorrupted = errors.New("steamcache: cache file corrupted") ErrInvalidContentLength = errors.New("steamcache: invalid content length") ErrRequestTimeout = errors.New("steamcache: request timeout") ErrRateLimitExceeded = errors.New("steamcache: rate limit exceeded") ErrInvalidUserAgent = errors.New("steamcache: invalid user agent") ) // SteamCacheError represents a SteamCache-specific error with context type SteamCacheError struct { Op string // Operation that failed URL string // URL that caused the error ClientIP string // Client IP address StatusCode int // HTTP status code if applicable Err error // Underlying error Context interface{} // Additional context } // Error implements the error interface func (e *SteamCacheError) Error() string { if e.URL != "" && e.ClientIP != "" { return fmt.Sprintf("steamcache: %s failed for URL %q from client %s: %v", e.Op, e.URL, e.ClientIP, e.Err) } if e.URL != "" { return fmt.Sprintf("steamcache: %s failed for URL %q: %v", e.Op, e.URL, e.Err) } return fmt.Sprintf("steamcache: %s failed: %v", e.Op, e.Err) } // Unwrap returns the underlying error func (e *SteamCacheError) Unwrap() error { return e.Err } // NewSteamCacheError creates a new SteamCache error with context func NewSteamCacheError(op, url, clientIP string, err error) *SteamCacheError { return &SteamCacheError{ Op: op, URL: url, ClientIP: clientIP, Err: err, } } // NewSteamCacheErrorWithStatus creates a new SteamCache error with HTTP status func NewSteamCacheErrorWithStatus(op, url, clientIP string, statusCode int, err error) *SteamCacheError { return &SteamCacheError{ Op: op, URL: url, ClientIP: clientIP, StatusCode: statusCode, Err: err, } } // NewSteamCacheErrorWithContext creates a new SteamCache error with additional context func NewSteamCacheErrorWithContext(op, url, clientIP string, context interface{}, err error) *SteamCacheError { return &SteamCacheError{ Op: op, URL: url, ClientIP: clientIP, Context: context, Err: err, } } // IsRetryableError determines if an error is retryable func IsRetryableError(err error) bool { if err == nil { return false } // Check for specific retryable errors if errors.Is(err, ErrUpstreamUnavailable) || errors.Is(err, ErrRequestTimeout) { return true } // Check for HTTP status codes that are retryable if steamErr, ok := err.(*SteamCacheError); ok { switch steamErr.StatusCode { case http.StatusServiceUnavailable, http.StatusGatewayTimeout, http.StatusTooManyRequests, http.StatusInternalServerError: return true } } return false } // IsClientError determines if an error is a client error (4xx) func IsClientError(err error) bool { if steamErr, ok := err.(*SteamCacheError); ok { return steamErr.StatusCode >= 400 && steamErr.StatusCode < 500 } return false } // IsServerError determines if an error is a server error (5xx) func IsServerError(err error) bool { if steamErr, ok := err.(*SteamCacheError); ok { return steamErr.StatusCode >= 500 } return false }