diff --git a/src/error.rs b/src/error.rs index 7b670a5..24173c1 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,6 +1,6 @@ +use std::{borrow::Cow, error::Error, fmt::Display}; + use serde::{Deserialize, Serialize}; -use std::error::Error; -use std::fmt::Display; #[derive(Debug)] pub enum KeycloakError { @@ -12,31 +12,53 @@ pub enum KeycloakError { }, } -#[derive(Debug, Clone, Deserialize, Serialize)] -pub struct KeycloakHttpError { - pub error: Option, - #[serde(rename = "errorMessage")] - pub error_message: Option, -} - impl From for KeycloakError { fn from(value: reqwest::Error) -> Self { KeycloakError::ReqwestFailure(value) } } -impl Error for KeycloakError { - fn description(&self) -> &str { - "keycloak error" - } +impl Error for KeycloakError {} - fn cause(&self) -> Option<&dyn Error> { - None +impl Display for KeycloakError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + KeycloakError::ReqwestFailure(e) => write!(f, "keycloak error (reqwest): {e}"), + KeycloakError::HttpFailure { status, body, text } => write!( + f, + "keycloak error (rest): {status} {}", + body.as_ref() + .and_then(|e| e.message()) + .unwrap_or_else(|| Cow::from(text)) + ), + } } } -impl Display for KeycloakError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "keycloak error") +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct KeycloakHttpError { + pub error: Option, + pub error_description: Option, + #[serde(rename = "errorMessage")] + pub error_message: Option, +} + +impl KeycloakHttpError { + pub fn message(&self) -> Option> { + self.error_message + .as_deref() + .map(Cow::from) + .or_else(|| { + self.error + .as_deref() + .map(|error| { + format!( + "{} [{error}]", + self.error_description.as_deref().unwrap_or("null") + ) + }) + .map(Cow::from) + }) + .or_else(|| self.error_description.as_deref().map(Cow::from)) } }