Implement proper error handling for URL shortening

This commit is contained in:
timvisee 2019-03-15 00:10:19 +01:00
parent cca5889e39
commit 6de33446c7
No known key found for this signature in database
GPG key ID: B8DB720BC383E172

View file

@ -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)
}
}