Skip to content

Commit

Permalink
refactor(errors): improve error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Guusvanmeerveld committed Aug 20, 2023
1 parent e7ab4fb commit 6792339
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 85 deletions.
9 changes: 4 additions & 5 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ use surf::http::Method;

use crate::{
dns::Dns,
error::{ErrorKind, Result},
failed,
error::{err, ErrorKind, Result},
http::{BasicCredentials, Http},
types::{
request::AutodiscoverRequest,
Expand Down Expand Up @@ -39,7 +38,7 @@ impl Client {
) -> Result<AutodiscoverResponse> {
match result {
AutodiscoverResult::Ok(config) => Ok(config),
AutodiscoverResult::Error(error) => failed!(
AutodiscoverResult::Error(error) => err!(
ErrorKind::InvalidConfig,
"The received config is invalid: {}",
error.message(),
Expand All @@ -48,14 +47,14 @@ impl Client {
match redirect_type {
RedirectType::Email(email_addr) => {
if email_addr == request.email() {
failed!(ErrorKind::InvalidConfig, "The returned config redirects us to the same email address that we are already requesting");
err!(ErrorKind::InvalidConfig, "The returned config redirects us to the same email address that we are already requesting");
}

request.set_email(email_addr);
}
RedirectType::Url(url) => {
if url == request.url() {
failed!(ErrorKind::InvalidConfig, "The returned config redirects us to the same url that we are already requesting");
err!(ErrorKind::InvalidConfig, "The returned config redirects us to the same url that we are already requesting");
}

request.set_url(url);
Expand Down
7 changes: 2 additions & 5 deletions src/dns.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use std::cmp::Ordering;

use crate::{
error::{ErrorKind, Result},
failed,
};
use crate::error::{err, ErrorKind, Result};

use trust_dns_resolver::{config::ResolverConfig, proto::rr::rdata::SRV};

Expand Down Expand Up @@ -97,7 +94,7 @@ impl Dns {
return Ok((record.record.target().to_string(), record.record.port()));
}

failed!(
err!(
ErrorKind::NotFound,
"Could not find any domains from the SRV query"
)
Expand Down
9 changes: 4 additions & 5 deletions src/email.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ use validator::validate_email;

use crate::{
client::Client,
error::{Error, ErrorKind, Result},
failed,
error::{err, Error, ErrorKind, Result},
types::{protocol::Protocol, request::AutodiscoverRequest, response::AutodiscoverResponse},
};

Expand All @@ -17,7 +16,7 @@ const INVALID_EMAIL_MESSAGE: &str = "The given email address is invalid";
/// Also validates that the given string is an email address.
fn domain_from_email<E: AsRef<str>>(email: E) -> Result<String> {
if !validate_email(email.as_ref()) {
failed!(ErrorKind::InvalidEmailAddress, "{}", INVALID_EMAIL_MESSAGE);
err!(ErrorKind::InvalidEmailAddress, "{}", INVALID_EMAIL_MESSAGE);
};

let mut email_split = email.as_ref().split('@');
Expand All @@ -26,7 +25,7 @@ fn domain_from_email<E: AsRef<str>>(email: E) -> Result<String> {

let domain = match email_split.next() {
Some(domain) => domain,
None => failed!(ErrorKind::InvalidEmailAddress, "{}", INVALID_EMAIL_MESSAGE),
None => err!(ErrorKind::InvalidEmailAddress, "{}", INVALID_EMAIL_MESSAGE),
};

Ok(domain.to_string())
Expand Down Expand Up @@ -178,7 +177,7 @@ pub async fn from_email<E: AsRef<str>, P: AsRef<str>, U: AsRef<str>>(
};

// If nothing return a valid configuration, we return an error.
failed!(
err!(
ErrorKind::ConfigNotFound(errors),
"Could not find any config for that email address",
)
Expand Down
84 changes: 44 additions & 40 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
use std::{fmt::Display, io::Error as IoError, result};
use std::{error, fmt::Display, io::Error as IoError, result};

use serde_xml_rs::Error as ParseXmlError;
use surf::Error as SurfError;
use trust_dns_resolver::error::ResolveError;

macro_rules! impl_from_error {
($error_type:ty, $error_kind:expr, $error_msg:expr) => {
impl From<$error_type> for Error {
fn from(err: $error_type) -> Self {
Error::new($error_kind(err), $error_msg)
}
}
};
}

macro_rules! err {
($kind:expr, $($arg:tt)*) => {{
use crate::error::Error;

let kind = $kind;
let message = format!($($arg)*);
return Err(Error::new( kind, message ));
}};
}

#[derive(Debug)]
pub enum ErrorKind {
InvalidConfig,
Expand All @@ -26,41 +46,34 @@ pub struct Error {
message: String,
}

impl error::Error for Error {}

impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Error: {}", self.message)
}
}

impl From<SurfError> for Error {
fn from(error: SurfError) -> Self {
Error::new(ErrorKind::Surf(error), "Failed to create http request")
}
}

impl From<ParseXmlError> for Error {
fn from(error: ParseXmlError) -> Self {
Error::new(
ErrorKind::ParseXml(error),
"An error while parsing the XML response",
)
}
}

impl From<IoError> for Error {
fn from(error: IoError) -> Self {
Error::new(ErrorKind::Io(error), "An error occurred in an io process")
}
}

impl From<ResolveError> for Error {
fn from(error: ResolveError) -> Self {
Error::new(
ErrorKind::Resolve(error),
"An error occurred while resolving a dns query",
)
}
}
impl_from_error!(
SurfError,
|err| ErrorKind::Surf(err),
"Failed to create http request"
);
impl_from_error!(
ParseXmlError,
|err| ErrorKind::ParseXml(err),
"An error while parsing the XML response"
);
impl_from_error!(
IoError,
|err| ErrorKind::Io(err),
"An error occurred in an io process"
);
impl_from_error!(
ResolveError,
|err| ErrorKind::Resolve(err),
"An error occurred while resolving a dns query"
);

impl Error {
pub fn new<M: Into<String>>(kind: ErrorKind, message: M) -> Self {
Expand All @@ -75,15 +88,6 @@ impl Error {
}
}

#[macro_export]
macro_rules! failed {
($kind:expr, $($arg:tt)*) => {{
use crate::error::Error;

let kind = $kind;
let message = format!($($arg)*);
return Err(Error::new( kind, message ));
}};
}
pub(crate) use err;

pub type Result<T> = result::Result<T, Error>;
40 changes: 20 additions & 20 deletions src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ use bytes::Bytes;
use log::debug;
use surf::{http::Method, Client as HttpClient, Config, Url};

use crate::{
error::{Error, ErrorKind, Result},
failed,
};
use crate::error::{err, ErrorKind, Result};

#[derive(Clone)]
/// Credentials used for HTTP Basic auth
Expand Down Expand Up @@ -59,15 +56,14 @@ impl Http {
const TIMEOUT: Duration = Duration::from_secs(10);

pub fn new() -> Result<Self> {
let client = Config::new()
.set_timeout(Some(Self::TIMEOUT))
.try_into()
.map_err(|err| {
Error::new(
ErrorKind::BuildHttpClient,
format!("Failed to create http client: {}", err),
)
})?;
let client = match Config::new().set_timeout(Some(Self::TIMEOUT)).try_into() {
Ok(client) => client,
Err(err) => err!(
ErrorKind::BuildHttpClient,
"Failed to create http client: {}",
err,
),
};

let http = Self { client };

Expand All @@ -82,12 +78,16 @@ impl Http {
body: Bytes,
basic_creds: Option<C>,
) -> Result<Bytes> {
Url::parse(url.as_ref()).map_err(|err| {
Error::new(
ErrorKind::InvalidRequestUrl,
format!("The provided request url is not valid: {}", err),
)
})?;
match Url::parse(url.as_ref()) {
Ok(_) => {}
Err(err) => {
err!(
ErrorKind::InvalidRequestUrl,
"The provided request url is not valid: {}",
err,
)
}
}

let mut request = self
.client
Expand All @@ -108,7 +108,7 @@ impl Http {
debug!("Status: {}", response.status(),);

if !response.status().is_success() {
failed!(
err!(
ErrorKind::HttpRequest,
"Http request returned status {}",
response.status()
Expand Down
7 changes: 2 additions & 5 deletions src/types/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ use surf::Url;
use super::pox::Autodiscover as PoxAutodiscover;

use super::response::AutodiscoverResult;
use crate::{
error::{ErrorKind, Result},
failed,
};
use crate::error::{err, ErrorKind, Result};

pub enum Protocol {
// SOAP,
Expand Down Expand Up @@ -92,7 +89,7 @@ impl Protocol {

// Ok(config.into())
// }
_ => failed!(
_ => err!(
ErrorKind::InvalidProtocol,
"There is valid protocol to handle the response"
),
Expand Down
7 changes: 2 additions & 5 deletions src/types/request.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use bytes::Bytes;

use crate::{
error::{ErrorKind, Result},
failed,
};
use crate::error::{err, ErrorKind, Result};

use super::protocol::Protocol;

Expand Down Expand Up @@ -34,7 +31,7 @@ impl AutodiscoverRequest {
match Protocol::from_url(&self.url) {
Some(url) => Ok(url),
None => {
failed!(ErrorKind::InvalidRequestUrl, "The request url is not valid")
err!(ErrorKind::InvalidRequestUrl, "The request url is not valid")
}
}
}
Expand Down

0 comments on commit 6792339

Please sign in to comment.