use reqwest::{blocking, Url};
pub use reqwest::{Method, StatusCode};
use serde::{Deserialize, Serialize};
use serde_json::to_string;
use std::borrow::Cow;
pub trait Query {
fn endpoint(&self) -> Cow<'static, str>;
fn params(&self) -> QueryParams {
QueryParams::default()
}
fn body(&self) -> Result<Option<&'static str>, &'static str> {
Ok(None)
}
}
#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct QueryParams<'a> {
pub params: Vec<(Cow<'a, str>, Cow<'a, str>)>,
}
pub trait Strategy {
type Type;
fn method(&self) -> Method;
fn execute(&self) -> Self::Type;
}
#[derive(Debug)]
pub struct Reqwest {
client: blocking::Client,
req_builder: Option<blocking::RequestBuilder>,
}
impl Default for Reqwest {
fn default() -> Self {
Self {
client: blocking::Client::new(),
req_builder: None,
}
}
}
impl Reqwest {
pub fn new(method: Method, endpoint: &str) -> Self {
let mut reqwest = Self {
client: blocking::Client::new(),
req_builder: None,
};
reqwest.init(method, endpoint);
reqwest
}
pub fn init(&mut self, method: Method, endpoint: &str) -> &mut Self {
self.req_builder =
Some(self.client.request(method, Self::parse_endpoint(endpoint)));
self
}
pub fn add_auth(&mut self, auth_token: &str) -> &mut Self {
self.req_builder = Some(self.get_req_builder().bearer_auth(auth_token));
self
}
pub fn add_query<T: Serialize>(&mut self, query: &T) -> &mut Self {
self.req_builder = Some(self.get_req_builder().query(query));
self
}
pub fn add_body<T: Serialize>(&mut self, model: T) -> &mut Self {
let json =
to_string(&model).expect("failed to serialize model to JSON");
self.req_builder = Some(self.get_req_builder().body(json.to_owned()));
self
}
pub fn send(&mut self) -> blocking::Response {
self.get_req_builder()
.send()
.expect("failed to make `reqwest`")
}
pub fn data<T: for<'de> Deserialize<'de>>(
&mut self,
) -> Result<T, StatusCode> {
let resp = self.send();
let status = resp.status();
if !status.is_success() {
return Err(resp.status());
}
Ok(resp.json::<T>().expect("failed to serialize `Response`"))
}
fn parse_endpoint(endpoint: &str) -> Url {
Url::parse(endpoint).expect("failed to parse `endpoint`")
}
fn get_req_builder(&mut self) -> blocking::RequestBuilder {
self.req_builder
.take()
.expect("uninitialised; no `req_builder` set")
}
}