Skip to content

Commit 6c539b8

Browse files
committed
Fix non-retryable error check in executeRequestWithRetries function
1 parent c4969de commit 6c539b8

File tree

2 files changed

+70
-29
lines changed

2 files changed

+70
-29
lines changed

errors/http_error_handling.go

Lines changed: 69 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -76,21 +76,43 @@ func HandleAPIError(resp *http.Response, log logger.Logger) error {
7676
// TranslateStatusCode provides a human-readable message for HTTP status codes.
7777
func TranslateStatusCode(statusCode int) string {
7878
messages := map[int]string{
79-
http.StatusOK: "Request successful.",
80-
http.StatusCreated: "Request to create or update resource successful.",
81-
http.StatusAccepted: "The request was accepted for processing, but the processing has not completed.",
82-
http.StatusNoContent: "Request successful. Resource successfully deleted.",
83-
http.StatusBadRequest: "Bad request. Verify the syntax of the request.",
84-
http.StatusUnauthorized: "Authentication failed. Verify the credentials being used for the request.",
85-
http.StatusForbidden: "Invalid permissions. Verify the account being used has the proper permissions for the resource you are trying to access.",
86-
http.StatusNotFound: "Resource not found. Verify the URL path is correct.",
87-
http.StatusConflict: "Conflict. See the error response for additional details.",
88-
http.StatusPreconditionFailed: "Precondition failed. See error description for additional details.",
89-
http.StatusRequestEntityTooLarge: "Payload too large.",
90-
http.StatusRequestURITooLong: "Request-URI too long.",
91-
http.StatusInternalServerError: "Internal server error. Retry the request or contact support if the error persists.",
92-
http.StatusBadGateway: "Bad Gateway. Generally due to a timeout issue.",
93-
http.StatusServiceUnavailable: "Service unavailable.",
79+
http.StatusOK: "Request successful.",
80+
http.StatusCreated: "Request to create or update resource successful.",
81+
http.StatusAccepted: "The request was accepted for processing, but the processing has not completed.",
82+
http.StatusNoContent: "Request successful. No content to send for this request.",
83+
http.StatusBadRequest: "Bad request. Verify the syntax of the request.",
84+
http.StatusUnauthorized: "Authentication failed. Verify the credentials being used for the request.",
85+
http.StatusPaymentRequired: "Payment required. Access to the requested resource requires payment.",
86+
http.StatusForbidden: "Invalid permissions. Verify the account has the proper permissions for the resource.",
87+
http.StatusNotFound: "Resource not found. Verify the URL path is correct.",
88+
http.StatusMethodNotAllowed: "Method not allowed. The method specified is not allowed for the resource.",
89+
http.StatusNotAcceptable: "Not acceptable. The server cannot produce a response matching the list of acceptable values.",
90+
http.StatusProxyAuthRequired: "Proxy authentication required. You must authenticate with a proxy server before this request can be served.",
91+
http.StatusRequestTimeout: "Request timeout. The server timed out waiting for the request.",
92+
http.StatusConflict: "Conflict. The request could not be processed because of conflict in the request.",
93+
http.StatusGone: "Gone. The resource requested is no longer available and will not be available again.",
94+
http.StatusLengthRequired: "Length required. The request did not specify the length of its content, which is required by the requested resource.",
95+
http.StatusPreconditionFailed: "Precondition failed. The server does not meet one of the preconditions specified in the request.",
96+
http.StatusRequestEntityTooLarge: "Payload too large. The request is larger than the server is willing or able to process.",
97+
http.StatusRequestURITooLong: "Request-URI too long. The URI provided was too long for the server to process.",
98+
http.StatusUnsupportedMediaType: "Unsupported media type. The request entity has a media type which the server or resource does not support.",
99+
http.StatusRequestedRangeNotSatisfiable: "Requested range not satisfiable. The client has asked for a portion of the file, but the server cannot supply that portion.",
100+
http.StatusExpectationFailed: "Expectation failed. The server cannot meet the requirements of the Expect request-header field.",
101+
http.StatusUnprocessableEntity: "Unprocessable entity. The server understands the content type and syntax of the request but was unable to process the contained instructions.",
102+
http.StatusLocked: "Locked. The resource that is being accessed is locked.",
103+
http.StatusFailedDependency: "Failed dependency. The request failed because it depended on another request and that request failed.",
104+
http.StatusUpgradeRequired: "Upgrade required. The client should switch to a different protocol.",
105+
http.StatusPreconditionRequired: "Precondition required. The server requires that the request be conditional.",
106+
http.StatusTooManyRequests: "Too many requests. The user has sent too many requests in a given amount of time.",
107+
http.StatusRequestHeaderFieldsTooLarge: "Request header fields too large. The server is unwilling to process the request because its header fields are too large.",
108+
http.StatusUnavailableForLegalReasons: "Unavailable for legal reasons. The server is denying access to the resource as a consequence of a legal demand.",
109+
http.StatusInternalServerError: "Internal server error. The server encountered an unexpected condition that prevented it from fulfilling the request.",
110+
http.StatusNotImplemented: "Not implemented. The server does not support the functionality required to fulfill the request.",
111+
http.StatusBadGateway: "Bad gateway. The server received an invalid response from the upstream server while trying to fulfill the request.",
112+
http.StatusServiceUnavailable: "Service unavailable. The server is currently unable to handle the request due to temporary overloading or maintenance.",
113+
http.StatusGatewayTimeout: "Gateway timeout. The server did not receive a timely response from the upstream server.",
114+
http.StatusHTTPVersionNotSupported: "HTTP version not supported. The server does not support the HTTP protocol version used in the request.",
115+
http.StatusNetworkAuthenticationRequired: "Network authentication required. The client needs to authenticate to gain network access.",
94116
}
95117

96118
if message, exists := messages[statusCode]; exists {
@@ -99,17 +121,34 @@ func TranslateStatusCode(statusCode int) string {
99121
return "An unexpected error occurred. Please try again later."
100122
}
101123

102-
// IsNonRetryableError checks if the provided response indicates a non-retryable error.
103-
func IsNonRetryableError(resp *http.Response) bool {
104-
// List of non-retryable HTTP status codes
124+
// IsNonRetryableStatusCode checks if the provided response indicates a non-retryable error.
125+
func IsNonRetryableStatusCode(resp *http.Response) bool {
126+
// Expanded list of non-retryable HTTP status codes
105127
nonRetryableStatusCodes := map[int]bool{
106-
http.StatusBadRequest: true, // 400
107-
http.StatusUnauthorized: true, // 401
108-
http.StatusForbidden: true, // 403
109-
http.StatusNotFound: true, // 404
110-
http.StatusConflict: true, // 409
111-
http.StatusRequestEntityTooLarge: true, // 413
112-
http.StatusRequestURITooLong: true, // 414
128+
http.StatusBadRequest: true, // 400 - Bad Request
129+
http.StatusUnauthorized: true, // 401 - Unauthorized
130+
http.StatusPaymentRequired: true, // 402 - Payment Required
131+
http.StatusForbidden: true, // 403 - Forbidden
132+
http.StatusNotFound: true, // 404 - Not Found
133+
http.StatusMethodNotAllowed: true, // 405 - Method Not Allowed
134+
http.StatusNotAcceptable: true, // 406 - Not Acceptable
135+
http.StatusProxyAuthRequired: true, // 407 - Proxy Authentication Required
136+
http.StatusConflict: true, // 409 - Conflict
137+
http.StatusGone: true, // 410 - Gone
138+
http.StatusLengthRequired: true, // 411 - Length Required
139+
http.StatusPreconditionFailed: true, // 412 - Precondition Failed
140+
http.StatusRequestEntityTooLarge: true, // 413 - Request Entity Too Large
141+
http.StatusRequestURITooLong: true, // 414 - Request-URI Too Long
142+
http.StatusUnsupportedMediaType: true, // 415 - Unsupported Media Type
143+
http.StatusRequestedRangeNotSatisfiable: true, // 416 - Requested Range Not Satisfiable
144+
http.StatusExpectationFailed: true, // 417 - Expectation Failed
145+
http.StatusUnprocessableEntity: true, // 422 - Unprocessable Entity
146+
http.StatusLocked: true, // 423 - Locked
147+
http.StatusFailedDependency: true, // 424 - Failed Dependency
148+
http.StatusUpgradeRequired: true, // 426 - Upgrade Required
149+
http.StatusPreconditionRequired: true, // 428 - Precondition Required
150+
http.StatusRequestHeaderFieldsTooLarge: true, // 431 - Request Header Fields Too Large
151+
http.StatusUnavailableForLegalReasons: true, // 451 - Unavailable For Legal Reasons
113152
}
114153

115154
_, isNonRetryable := nonRetryableStatusCodes[resp.StatusCode]
@@ -124,16 +163,18 @@ func IsRateLimitError(resp *http.Response) bool {
124163
// IsTransientError checks if an error or HTTP response indicates a transient error.
125164
func IsTransientError(resp *http.Response) bool {
126165
transientStatusCodes := map[int]bool{
127-
http.StatusInternalServerError: true,
128-
http.StatusBadGateway: true,
129-
http.StatusServiceUnavailable: true,
166+
http.StatusInternalServerError: true, // 500 Internal Server Error
167+
http.StatusBadGateway: true, // 502 Bad Gateway
168+
http.StatusServiceUnavailable: true, // 503 Service Unavailable
169+
http.StatusGatewayTimeout: true, // 504 - Gateway Timeout
130170
}
131171
return resp != nil && transientStatusCodes[resp.StatusCode]
132172
}
133173

134174
// IsRetryableStatusCode checks if the provided HTTP status code is considered retryable.
135175
func IsRetryableStatusCode(statusCode int) bool {
136176
retryableStatusCodes := map[int]bool{
177+
http.StatusRequestTimeout: true, // 408 - Request Timeout
137178
http.StatusTooManyRequests: true, // 429
138179
http.StatusInternalServerError: true, // 500
139180
http.StatusBadGateway: true, // 502

httpclient/httpclient_request.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ func (c *Client) executeRequestWithRetries(method, endpoint string, body, out in
162162
return resp, c.handleSuccessResponse(resp, out, log, method, endpoint)
163163
}
164164
// Check for non-retryable errors
165-
if resp != nil && errors.IsNonRetryableError(resp) {
165+
if resp != nil && errors.IsNonRetryableStatusCode(resp) {
166166
log.Info("Non-retryable error received", zap.Int("status_code", resp.StatusCode))
167167
return resp, errors.HandleAPIError(resp, log)
168168
}

0 commit comments

Comments
 (0)