use tracing::info;
use tracing::warn;
use crate::Error;
use crate::Res;
use crate::error::LoginError;
use quilt_uri::Host;
pub(super) fn is_token_auth_error(e: &Error) -> bool {
matches!(
e,
Error::Reqwest(re) if re.status().is_some_and(|s| s == 400 || s == 401 || s == 403)
)
}
pub(super) fn is_credentials_auth_error(e: &Error) -> bool {
matches!(
e,
Error::Reqwest(re) if re.status().is_some_and(|s| s == 401 || s == 403)
)
}
pub(super) fn http_status(e: &Error) -> Option<u16> {
match e {
Error::Reqwest(re) => re.status().map(|s| s.as_u16()),
_ => None,
}
}
pub(super) fn classify_retry_outcome<T>(
result: Res<T>,
is_auth_error: fn(&Error) -> bool,
endpoint: &str,
host: &Host,
) -> Res<T> {
match result {
Ok(v) => {
info!(
"✔️ Recovered from transient auth error on {} for {}",
endpoint, host
);
Ok(v)
}
Err(e) if is_auth_error(&e) => {
warn!(
status = ?http_status(&e),
"❌ Auth error on {} for {} persisted after retry, login required: {}",
endpoint, host, e
);
Err(LoginError::Required(Some(host.to_owned())).into())
}
Err(e) => {
warn!(
status = ?http_status(&e),
"❌ Failed to refresh via {} for {} on retry: {}",
endpoint, host, e
);
Err(e)
}
}
}