brasilapi-client 0.2.2

Rust client implementation to consume BrasilAPI
Documentation

use crate::errors::Error;
use log::{Level, debug, error, log_enabled, trace, warn};
use serde::{de::DeserializeOwned, Serialize};
use serde_json::{from_str};

pub(crate) async fn get<Input: Serialize + std::fmt::Debug, Output: 'static + DeserializeOwned>(
    url: &str
) -> Result<Output, Error> {
    use isahc::*;

    trace!("GET Req on {}", url);

    let mut resp = isahc::get_async(url)
    .await
    .map_err(|_|crate::errors::Error::NotExpectedRequestError)
    .unwrap();

    let status = resp.status().as_u16();
    let mut body = resp.text().await.map_err(|e| crate::errors::Error::HttpError(e.into()))?;

    if body.is_empty() {
        body = "null".to_string();
    }

    parse_response(status, body)

}

fn parse_response<Output: DeserializeOwned>(
    status_code: u16,
    body: String,
) -> Result<Output, Error> {
    if (200..=204).contains(&status_code) {
        match from_str::<Output>(&body) {
            Ok(output) => {
                trace!("Request succeed");
                if log_enabled!(Level::Debug) {
                    debug!("Response: {}", &body);
                }

                return Ok(output);
            }
            Err(e) => {
                error!("Request succeed but failed to parse response");
                return Err(Error::SerdeJsonError(e));
            }
        };
    }
    warn!("Expected success response code, got {}", status_code);
    match from_str(&body) {
        Ok(e) => {
            trace!("Request failed");
            if log_enabled!(Level::Debug) {
                debug!("Response: {}", &body);
            }

            Err(Error::from(&e))
        },
        Err(e) => Err(Error::SerdeJsonError(e)),
    }
}