mirror of
https://github.com/lukaszraczylo/graphql-monitoring-proxy.git
synced 2026-06-05 23:03:48 +00:00
Add LRU cache support.
This commit is contained in:
@@ -106,117 +106,8 @@ func (e *ProxyError) WithMetadata(key string, value interface{}) *ProxyError {
|
||||
return e
|
||||
}
|
||||
|
||||
// Common error constructors
|
||||
|
||||
// NewConnectionError creates a connection-related error
|
||||
func NewConnectionError(err error) *ProxyError {
|
||||
code := ErrCodeConnectionRefused
|
||||
if err != nil {
|
||||
errStr := err.Error()
|
||||
if contains(errStr, "reset") {
|
||||
code = ErrCodeConnectionReset
|
||||
}
|
||||
}
|
||||
|
||||
return NewProxyError(code, "Failed to connect to backend", 502, true).
|
||||
WithCause(err)
|
||||
}
|
||||
|
||||
// NewTimeoutError creates a timeout error
|
||||
func NewTimeoutError(err error) *ProxyError {
|
||||
return NewProxyError(ErrCodeTimeout, "Request timed out", 504, false).
|
||||
WithCause(err)
|
||||
}
|
||||
|
||||
// NewCircuitOpenError creates a circuit breaker open error
|
||||
func NewCircuitOpenError() *ProxyError {
|
||||
return NewProxyError(ErrCodeCircuitOpen, "Service temporarily unavailable due to circuit breaker", 503, false).
|
||||
WithDetails("The backend service is currently experiencing issues. Please try again later.")
|
||||
}
|
||||
|
||||
// NewRateLimitError creates a rate limit error
|
||||
func NewRateLimitError(userID, role string) *ProxyError {
|
||||
return NewProxyError(ErrCodeRateLimited, "Rate limit exceeded", 429, false).
|
||||
WithDetails("You have exceeded the rate limit for your role").
|
||||
WithMetadata("user_id", userID).
|
||||
WithMetadata("role", role)
|
||||
}
|
||||
|
||||
// NewBackendError creates a backend error from status code
|
||||
func NewBackendError(statusCode int, body string) *ProxyError {
|
||||
code := ErrCodeBackendError
|
||||
message := "Backend returned an error"
|
||||
retryable := false
|
||||
|
||||
switch {
|
||||
case statusCode == 429:
|
||||
code = ErrCodeRateLimited
|
||||
message = "Backend rate limit exceeded"
|
||||
retryable = true
|
||||
case statusCode == 503:
|
||||
code = ErrCodeServiceUnavailable
|
||||
message = "Backend service unavailable"
|
||||
retryable = true
|
||||
case statusCode == 502 || statusCode == 504:
|
||||
code = ErrCodeBadGateway
|
||||
message = "Bad gateway"
|
||||
retryable = true
|
||||
case statusCode >= 500:
|
||||
code = ErrCodeBackendError
|
||||
message = "Backend server error"
|
||||
retryable = true
|
||||
case statusCode == 404:
|
||||
code = ErrCodeNotFound
|
||||
message = "Resource not found"
|
||||
case statusCode == 403:
|
||||
code = ErrCodeForbidden
|
||||
message = "Access forbidden"
|
||||
case statusCode == 401:
|
||||
code = ErrCodeUnauthorized
|
||||
message = "Unauthorized"
|
||||
case statusCode >= 400:
|
||||
code = ErrCodeInvalidRequest
|
||||
message = "Invalid request"
|
||||
}
|
||||
|
||||
return NewProxyError(code, message, statusCode, retryable).
|
||||
WithMetadata("backend_status", statusCode).
|
||||
WithMetadata("backend_body", truncateString(body, 500))
|
||||
}
|
||||
|
||||
// NewInvalidResponseError creates an invalid response error
|
||||
func NewInvalidResponseError(details string) *ProxyError {
|
||||
return NewProxyError(ErrCodeInvalidResponse, "Backend returned invalid response", 502, false).
|
||||
WithDetails(details)
|
||||
}
|
||||
|
||||
// NewInternalError creates an internal error
|
||||
func NewInternalError(err error) *ProxyError {
|
||||
return NewProxyError(ErrCodeInternalError, "Internal proxy error", 500, false).
|
||||
WithCause(err)
|
||||
}
|
||||
|
||||
// NewContextCanceledError creates a context canceled error
|
||||
func NewContextCanceledError() *ProxyError {
|
||||
return NewProxyError(ErrCodeContextCanceled, "Request canceled", 499, false).
|
||||
WithDetails("The request was canceled by the client")
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
|
||||
func contains(s, substr string) bool {
|
||||
return len(s) > 0 && len(substr) > 0 && len(s) >= len(substr) && (s == substr || len(s) > len(substr) && (s[:len(substr)] == substr || s[len(s)-len(substr):] == substr || containsMiddle(s, substr)))
|
||||
}
|
||||
|
||||
func containsMiddle(s, substr string) bool {
|
||||
for i := 0; i <= len(s)-len(substr); i++ {
|
||||
if s[i:i+len(substr)] == substr {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func truncateString(s string, maxLen int) string {
|
||||
if len(s) <= maxLen {
|
||||
return s
|
||||
|
||||
Reference in New Issue
Block a user