wildland-http-client 0.40.0

Wildland http client
Documentation
use std::collections::HashMap;
use std::rc::Rc;

use serde::Deserialize;
use serde_json::json;
use thiserror::Error;

#[cfg(target_os = "emscripten")]
mod emscripten_http_client;

#[cfg(target_os = "emscripten")]
pub(crate) use emscripten_http_client::EmscriptenHttpClient as CurrentPlatformClient;

#[cfg(not(target_os = "emscripten"))]
mod minreq_http_client;

#[cfg(not(target_os = "emscripten"))]
pub(crate) use minreq_http_client::MinreqHttpClient as CurrentPlatformClient;

#[derive(Error, Debug, Clone)]
pub enum HttpError {
    #[error("{0}")]
    Generic(String),
    #[error("{0}")]
    InvalidResponseUTF8Body(#[from] std::string::FromUtf8Error),
    #[error("{0}")]
    InvalidResponseJsonBody(#[from] Rc<serde_json::Error>),
}

#[derive(Debug, Clone)]
pub(crate) struct Response {
    pub(crate) status_code: i32,
    pub(crate) body: Vec<u8>,
}

impl Response {
    pub fn to_string(&self) -> Result<String, HttpError> {
        Ok(String::from_utf8(self.body.clone())?)
    }

    pub fn deserialize<'a, T>(&'a self) -> Result<T, HttpError>
    where
        T: Deserialize<'a>,
    {
        Ok(serde_json::from_slice(&self.body).map_err(Rc::new)?)
    }
}

pub(crate) type HttpResult = Result<Response, HttpError>;

#[derive(Debug, Clone, PartialEq)]
pub(crate) struct Request {
    url: String,
    json: Option<serde_json::Value>,
    headers: HashMap<String, String>,
}

impl Request {
    pub fn new<T>(url: T) -> Self
    where
        T: Into<String>,
    {
        Request {
            url: url.into(),
            json: None,
            headers: HashMap::default(),
        }
    }

    pub fn with_json<T>(mut self, json: &T) -> Self
    where
        T: serde::Serialize,
    {
        self.json = Some(json!(json));
        self
    }

    pub fn with_header<T, U>(mut self, key: T, val: U) -> Self
    where
        T: Into<String>,
        U: Into<String>,
    {
        self.headers.insert(key.into(), val.into());
        self
    }
}

#[cfg_attr(test, mockall::automock)]
pub(crate) trait HttpClient {
    fn post(&self, request: Request) -> HttpResult;
    fn put(&self, request: Request) -> HttpResult;
}