drova_plugins 1.0.1

Main plugins for drova
Documentation
use async_trait::async_trait;
use drova_sdk::{Error, Protocol, Response, ResponseData};
use mime::Mime;
use reqwest::header::CONTENT_TYPE;

use crate::utils::mime_to_str;

pub struct HttpProtocol;

#[async_trait]
impl Protocol for HttpProtocol {
    async fn fetch(&self, url: &url::Url) -> Result<Response, Error> {
        let res = reqwest::get(url.to_string())
            .await
            .map_err(match_reqwest_error)?;

        let mime = mime_to_str(
            {
                match res.headers().get(CONTENT_TYPE) {
                    Some(header) => match header.to_str() {
                        Ok(mime) => mime.to_owned(),
                        Err(_) => "text/plain".to_owned(),
                    },
                    None => "text/plain".to_owned(),
                }
            }
            .parse::<Mime>()
            .map_err(|_| Error::InvalidMimeType)?,
        );

        match mime.starts_with("text") {
            true => Ok(Response {
                data: ResponseData::TextOutput(res.text().await.map_err(match_reqwest_error)?),
                mime,
            }),
            false => Ok(Response {
                data: ResponseData::BitsOutput(
                    res.bytes().await.map_err(match_reqwest_error)?.to_vec(),
                ),
                mime,
            }),
        }
    }
}

fn match_reqwest_error(e: reqwest::Error) -> Error {
    match e.status() {
        Some(s) => match s.as_u16() {
            400 => Error::BadRequest,
            401 => Error::NotAuthorized,
            403 => Error::Forbidden,
            404 => Error::NotFound,
            405 => Error::MethodNotAllowed,
            406 => Error::NotAcceptable,
            410 => Error::Gone,
            429 => Error::TooManyRequests,
            500 => Error::Failure,
            503 => Error::ServerUnavailable,
            s => Error::UnknownStatus(s.into()),
        },
        None => Error::InvalidStatus,
    }
}