Improve HttpError mapping (#2370)

* Use reqwest From impl in HttpError From impl

* Map timeouts to NetworkError (dae)
This commit is contained in:
RumovZ 2023-02-08 03:54:42 +01:00 committed by GitHub
parent 567ba06b5c
commit ed54cf71ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,8 +1,6 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use std::error::Error;
use anki_i18n::I18n; use anki_i18n::I18n;
use reqwest::StatusCode; use reqwest::StatusCode;
use snafu::Snafu; use snafu::Snafu;
@ -66,8 +64,8 @@ impl AnkiError {
} }
} }
impl From<reqwest::Error> for AnkiError { impl From<&reqwest::Error> for AnkiError {
fn from(err: reqwest::Error) -> Self { fn from(err: &reqwest::Error) -> Self {
let url = err.url().map(|url| url.as_str()).unwrap_or(""); let url = err.url().map(|url| url.as_str()).unwrap_or("");
let str_err = format!("{}", err); let str_err = format!("{}", err);
// strip url from error to avoid exposing keys // strip url from error to avoid exposing keys
@ -88,6 +86,12 @@ impl From<reqwest::Error> for AnkiError {
} }
} }
impl From<reqwest::Error> for AnkiError {
fn from(err: reqwest::Error) -> Self {
err.into()
}
}
fn error_for_status_code(info: String, code: StatusCode) -> AnkiError { fn error_for_status_code(info: String, code: StatusCode) -> AnkiError {
use reqwest::StatusCode as S; use reqwest::StatusCode as S;
match code { match code {
@ -208,26 +212,20 @@ impl NetworkError {
// encountered instead of trying to determine the problem later. // encountered instead of trying to determine the problem later.
impl From<HttpError> for AnkiError { impl From<HttpError> for AnkiError {
fn from(err: HttpError) -> Self { fn from(err: HttpError) -> Self {
if let Some(source) = &err.source { if let Some(reqwest_error) = err
if let Some(err) = source.downcast_ref::<reqwest::Error>() { .source
if let Some(status) = err.status() { .as_ref()
let kind = match status { .and_then(|source| source.downcast_ref::<reqwest::Error>())
StatusCode::CONFLICT => SyncErrorKind::Conflict, {
StatusCode::NOT_IMPLEMENTED => SyncErrorKind::ClientTooOld, reqwest_error.into()
StatusCode::FORBIDDEN => SyncErrorKind::AuthFailed, } else if err.code == StatusCode::REQUEST_TIMEOUT {
StatusCode::INTERNAL_SERVER_ERROR => SyncErrorKind::ServerError, NetworkError {
StatusCode::BAD_REQUEST => SyncErrorKind::DatabaseCheckRequired, info: String::new(),
_ => SyncErrorKind::Other, kind: NetworkErrorKind::Timeout,
};
let info = format!("{:?}", err);
// in the future we should chain the error instead of discarding it
return AnkiError::sync_error(info, kind);
} else if let Some(source) = err.source() {
let info = format!("{:?}", source);
return AnkiError::sync_error(info, SyncErrorKind::Other);
}
} }
.into()
} else {
AnkiError::sync_error(format!("{:?}", err), SyncErrorKind::Other)
} }
AnkiError::sync_error(format!("{:?}", err), SyncErrorKind::Other)
} }
} }