fix: improve server error messages to include HTTP status code (#5532)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -68,6 +68,16 @@ fn check_context_length_exceeded(text: &str) -> bool {
|
|||||||
.any(|phrase| text_lower.contains(phrase))
|
.any(|phrase| text_lower.contains(phrase))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn format_server_error_message(status_code: StatusCode, payload: Option<&Value>) -> String {
|
||||||
|
match payload {
|
||||||
|
Some(Value::Null) | None => format!(
|
||||||
|
"HTTP {}: No response body received from server",
|
||||||
|
status_code.as_u16()
|
||||||
|
),
|
||||||
|
Some(p) => format!("HTTP {}: {}", status_code.as_u16(), p),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn map_http_error_to_provider_error(
|
pub fn map_http_error_to_provider_error(
|
||||||
status: StatusCode,
|
status: StatusCode,
|
||||||
payload: Option<Value>,
|
payload: Option<Value>,
|
||||||
@@ -79,7 +89,7 @@ pub fn map_http_error_to_provider_error(
|
|||||||
"Authentication failed. Please ensure your API keys are valid and have the required permissions. \
|
"Authentication failed. Please ensure your API keys are valid and have the required permissions. \
|
||||||
Status: {}{}",
|
Status: {}{}",
|
||||||
status,
|
status,
|
||||||
payload.as_ref().map(|p| format!(". Response: {:?}", p)).unwrap_or_default()
|
payload.as_ref().map(|p| format!(". Response: {}", p)).unwrap_or_default()
|
||||||
);
|
);
|
||||||
ProviderError::Authentication(message)
|
ProviderError::Authentication(message)
|
||||||
}
|
}
|
||||||
@@ -116,7 +126,9 @@ pub fn map_http_error_to_provider_error(
|
|||||||
details: format!("{:?}", payload),
|
details: format!("{:?}", payload),
|
||||||
retry_delay: None,
|
retry_delay: None,
|
||||||
},
|
},
|
||||||
_ if status.is_server_error() => ProviderError::ServerError(format!("{:?}", payload)),
|
_ if status.is_server_error() => {
|
||||||
|
ProviderError::ServerError(format_server_error_message(status, payload.as_ref()))
|
||||||
|
}
|
||||||
_ => ProviderError::RequestFailed(format!("Request failed with status: {}", status)),
|
_ => ProviderError::RequestFailed(format!("Request failed with status: {}", status)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -295,12 +307,9 @@ pub async fn handle_response_google_compat(response: Response) -> Result<Value,
|
|||||||
retry_delay,
|
retry_delay,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ if final_status.is_server_error() => {
|
_ if final_status.is_server_error() => Err(ProviderError::ServerError(
|
||||||
Err(ProviderError::ServerError(format!("{:?}", payload)))
|
format_server_error_message(final_status, payload.as_ref()),
|
||||||
}
|
)),
|
||||||
StatusCode::INTERNAL_SERVER_ERROR | StatusCode::SERVICE_UNAVAILABLE => {
|
|
||||||
Err(ProviderError::ServerError(format!("{:?}", payload)))
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
"{}", format!("Provider request failed with status: {}. Payload: {:?}", final_status, payload)
|
"{}", format!("Provider request failed with status: {}. Payload: {:?}", final_status, payload)
|
||||||
@@ -1059,15 +1068,13 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_map_http_error_to_provider_error() {
|
fn test_map_http_error_to_provider_error() {
|
||||||
let test_cases = vec![
|
let test_cases = vec![
|
||||||
// UNAUTHORIZED/FORBIDDEN - with payload
|
|
||||||
(
|
(
|
||||||
StatusCode::UNAUTHORIZED,
|
StatusCode::UNAUTHORIZED,
|
||||||
Some(json!({"error": "auth failed"})),
|
Some(json!({"error": "auth failed"})),
|
||||||
ProviderError::Authentication(
|
ProviderError::Authentication(
|
||||||
"Authentication failed. Please ensure your API keys are valid and have the required permissions. Status: 401 Unauthorized. Response: Object {\"error\": String(\"auth failed\")}".to_string(),
|
"Authentication failed. Please ensure your API keys are valid and have the required permissions. Status: 401 Unauthorized. Response: {\"error\":\"auth failed\"}".to_string(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// UNAUTHORIZED/FORBIDDEN - without payload
|
|
||||||
(
|
(
|
||||||
StatusCode::FORBIDDEN,
|
StatusCode::FORBIDDEN,
|
||||||
None,
|
None,
|
||||||
@@ -1075,7 +1082,6 @@ mod tests {
|
|||||||
"Authentication failed. Please ensure your API keys are valid and have the required permissions. Status: 403 Forbidden".to_string(),
|
"Authentication failed. Please ensure your API keys are valid and have the required permissions. Status: 403 Forbidden".to_string(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// BAD_REQUEST - with context_length_exceeded detection
|
|
||||||
(
|
(
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
Some(json!({"error": {"message": "context_length_exceeded"}})),
|
Some(json!({"error": {"message": "context_length_exceeded"}})),
|
||||||
@@ -1083,7 +1089,6 @@ mod tests {
|
|||||||
"{\"error\":{\"message\":\"context_length_exceeded\"}}".to_string(),
|
"{\"error\":{\"message\":\"context_length_exceeded\"}}".to_string(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// BAD_REQUEST - with error.message extraction
|
|
||||||
(
|
(
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
Some(json!({"error": {"message": "Custom error"}})),
|
Some(json!({"error": {"message": "Custom error"}})),
|
||||||
@@ -1091,7 +1096,6 @@ mod tests {
|
|||||||
"Request failed with status: 400 Bad Request. Message: Custom error".to_string(),
|
"Request failed with status: 400 Bad Request. Message: Custom error".to_string(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// BAD_REQUEST - without payload
|
|
||||||
(
|
(
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
None,
|
None,
|
||||||
@@ -1099,7 +1103,6 @@ mod tests {
|
|||||||
"Request failed with status: 400 Bad Request".to_string(),
|
"Request failed with status: 400 Bad Request".to_string(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// TOO_MANY_REQUESTS
|
|
||||||
(
|
(
|
||||||
StatusCode::TOO_MANY_REQUESTS,
|
StatusCode::TOO_MANY_REQUESTS,
|
||||||
Some(json!({"retry_after": 60})),
|
Some(json!({"retry_after": 60})),
|
||||||
@@ -1108,17 +1111,29 @@ mod tests {
|
|||||||
retry_delay: None,
|
retry_delay: None,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
// is_server_error() without payload
|
|
||||||
(
|
(
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
None,
|
None,
|
||||||
ProviderError::ServerError("None".to_string()),
|
ProviderError::ServerError(format_server_error_message(
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
None,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Some(Value::Null),
|
||||||
|
ProviderError::ServerError(format_server_error_message(
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Some(&Value::Null),
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
// is_server_error() with payload
|
|
||||||
(
|
(
|
||||||
StatusCode::BAD_GATEWAY,
|
StatusCode::BAD_GATEWAY,
|
||||||
Some(json!({"error": "upstream error"})),
|
Some(json!({"error": "upstream error"})),
|
||||||
ProviderError::ServerError("Some(Object {\"error\": String(\"upstream error\")})".to_string()),
|
ProviderError::ServerError(format_server_error_message(
|
||||||
|
StatusCode::BAD_GATEWAY,
|
||||||
|
Some(&json!({"error": "upstream error"})),
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
// Default - any other status code
|
// Default - any other status code
|
||||||
(
|
(
|
||||||
|
|||||||
Reference in New Issue
Block a user