From 6cfc0e18181a8c93906ed4ea25eb68796e0f4720 Mon Sep 17 00:00:00 2001 From: Erk Date: Wed, 1 May 2019 13:26:11 +0200 Subject: [PATCH] Make the HttpError Send+Sync (#532) --- Cargo.toml | 4 +++ src/http/error.rs | 79 ++++++++++++++++++++++++++++++++++++++++++++--- src/http/raw.rs | 6 ++-- 3 files changed, 82 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 937bdd4dda0..148b9d0d182 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -97,6 +97,10 @@ version = "^0.19" optional = true version = "^0.16" +[dev-dependencies.http_crate] +version = "~0.1" +package = "http" + [dev-dependencies.matches] version = "^0.1" diff --git a/src/http/error.rs b/src/http/error.rs index 67258d16bb4..212e8c678c1 100644 --- a/src/http/error.rs +++ b/src/http/error.rs @@ -2,7 +2,9 @@ use reqwest::{ Error as ReqwestError, header::InvalidHeaderValue, Response, - UrlError + StatusCode, + Url, + UrlError, }; use std::{ error::Error as StdError, @@ -13,10 +15,46 @@ use std::{ } }; +#[derive(Clone, Serialize, Deserialize, PartialEq)] +pub struct DiscordJsonError { + pub code: isize, + pub message: String, + #[serde(skip)] + non_exhaustive: (), +} + +impl std::fmt::Debug for DiscordJsonError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "\"{}\"", self.message) + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct ErrorResponse { + pub status_code: StatusCode, + pub url: Url, + pub error: DiscordJsonError, +} + +impl From for ErrorResponse { + fn from(mut r: Response) -> Self { + ErrorResponse { + status_code: r.status(), + url: r.url().clone(), + error: r.json().unwrap_or_else(|_| DiscordJsonError { + code: -1, + message: "[Serenity] No correct json was recieved!".to_string(), + non_exhaustive: (), + }), + } + } +} + + #[derive(Debug)] pub enum Error { /// When a non-successful status code was received for a request. - UnsuccessfulRequest(Box), + UnsuccessfulRequest(ErrorResponse), /// When the decoding of a ratelimit header could not be properly decoded /// into an `i64`. RateLimitI64, @@ -57,8 +95,8 @@ impl Display for Error { impl StdError for Error { fn description(&self) -> &str { - match *self { - Error::UnsuccessfulRequest(_) => "A non-successful response status code was received", + match self { + Error::UnsuccessfulRequest(ref e) => &e.error.message, Error::RateLimitI64 => "Error decoding a header into an i64", Error::RateLimitUtf8 => "Error decoding a header from UTF-8", Error::Url(_) => "Provided URL is incorrect.", @@ -68,3 +106,36 @@ impl StdError for Error { } } } + +#[cfg(test)] +mod test { + use super::*; + use http_crate::response::Builder; + use reqwest::r#async::ResponseBuilderExt; + + #[test] + fn test_error_response_into() { + let error = DiscordJsonError { + code: 43121215, + message: String::from("This is a Ferris error"), + non_exhaustive: (), + }; + + let mut builder = Builder::new(); + builder.status(403); + builder.url(String::from("https://ferris.crab").parse().unwrap()); + let body_string = serde_json::to_string(&error).unwrap(); + let response = builder.body(body_string.into_bytes()).unwrap(); + + let reqwest_response: reqwest::Response = response.into(); + let error_response: ErrorResponse = reqwest_response.into(); + + let known = ErrorResponse { + status_code: reqwest::StatusCode::from_u16(403).unwrap(), + url: String::from("https://ferris.crab").parse().unwrap(), + error: error, + }; + + assert_eq!(error_response, known); + } +} diff --git a/src/http/raw.rs b/src/http/raw.rs index f6eebed0bb0..f94e4af7a3f 100644 --- a/src/http/raw.rs +++ b/src/http/raw.rs @@ -1529,7 +1529,7 @@ impl Http { .multipart(multipart).send()?; if !response.status().is_success() { - return Err(HttpError::UnsuccessfulRequest(Box::new(response)).into()); + return Err(HttpError::UnsuccessfulRequest(response.into()).into()); } serde_json::from_reader(response).map_err(From::from) @@ -1723,7 +1723,7 @@ impl Http { if response.status().is_success() { Ok(response) } else { - Err(Error::from(HttpError::UnsuccessfulRequest(Box::new(response)))) + Err(Error::Http(Box::new(HttpError::UnsuccessfulRequest(response.into())))) } } @@ -1768,7 +1768,7 @@ impl Http { debug!("Expected {}, got {}", expected, response.status()); trace!("Unsuccessful response: {:?}", response); - Err(Error::from(HttpError::UnsuccessfulRequest(Box::new(response)))) + Err(Error::Http(Box::new(HttpError::UnsuccessfulRequest(response.into())))) } }