Ver código fonte

Implement proper error handling for URL shortening

timvisee 6 anos atrás
pai
commit
6de33446c7
1 arquivos alterados com 50 adições e 6 exclusões
  1. 50 6
      src/urlshorten.rs

+ 50 - 6
src/urlshorten.rs

@@ -1,27 +1,33 @@
 //! URL shortening mechanics.
 
 use ffsend_api::{
+    api::request::{ensure_success, ResponseError},
     url::{self, Url},
-    reqwest::Client,
+    reqwest::{self, Client},
 };
 use urlshortener::{
     providers::{Provider, self},
     request::{Method, Request},
 };
 
+/// An URL shortening result.
+type Result<T> = ::std::result::Result<T, Error>;
+
 /// Shorten the given URL.
-pub fn shorten(client: &Client, url: &str) -> String {
+pub fn shorten(client: &Client, url: &str) -> Result<String> {
     // TODO: allow selecting other shorteners
     request(client, providers::request(url, &Provider::IsGd))
 }
 
 /// Shorten the given URL.
-pub fn shorten_url(client: &Client, url: &Url) -> Result<Url, url::ParseError> {
-    Url::parse(&shorten(client, url.as_str()))
+pub fn shorten_url(client: &Client, url: &Url) -> Result<Url> {
+    Url::parse(
+        &shorten(client, url.as_str())?,
+    ).map_err(|err| err.into())
 }
 
 /// Do the request as given, return the response.
-fn request(client: &Client, req: Request) -> String {
+fn request(client: &Client, req: Request) -> Result<String> {
     // Start the request builder
     let mut builder = match req.method {
         Method::Get => client.get(&req.url),
@@ -52,5 +58,43 @@ fn request(client: &Client, req: Request) -> String {
         builder = builder.body(body);
     }
 
-    builder.send().expect("failed to send shorten request").text().expect("failed to get text")
+    // Send the request, ensure success
+    let mut response = builder.send()
+        .map_err(Error::Request)?;
+    ensure_success(&response)?;
+
+    // Respond with the body text
+    response.text().map_err(Error::Malformed)
+}
+
+/// An URL shortening error.
+#[derive(Debug, Fail)]
+pub enum Error {
+    /// Failed to send the shortening request.
+    #[fail(display = "failed to send URL shorten request")]
+    Request(#[cause] reqwest::Error),
+
+    /// The server responded with a bad response.
+    #[fail(display = "failed to shorten URL, got bad response")]
+    Response(#[cause] ResponseError),
+
+    /// The server resonded with a malformed repsonse.
+    #[fail(display = "failed to shorten URL, got malformed response")]
+    Malformed(#[cause] reqwest::Error),
+
+    /// An error occurred while parsing the shortened URL.
+    #[fail(display = "failed to shorten URL, could not parse URL")]
+    Url(#[cause] url::ParseError)
+}
+
+impl From<url::ParseError> for Error {
+    fn from(err: url::ParseError) -> Self {
+        Error::Url(err)
+    }
+}
+
+impl From<ResponseError> for Error {
+    fn from(err: ResponseError) -> Self {
+        Error::Response(err)
+    }
 }