use crate::{
errors::ReqwestBuilderError,
serialization::{construct_url, serialize_to_form_params, serialize_to_header_map},
types::{QueryParams, RequestBody},
};
use serde::Serialize;
use url::Url;
pub trait IntoReqwestBuilder
where
Self: Sized + Serialize,
{
type Headers: Serialize + Clone;
fn method(&self) -> http::Method;
fn endpoint(&self) -> String;
fn headers(&self) -> Option<Self::Headers> {
None
}
fn body(&self) -> RequestBody {
RequestBody::Json
}
fn query_params(&self) -> Option<QueryParams> {
None
}
fn create_multipart_form(&self) -> Option<reqwest::multipart::Form> {
None
}
fn into_reqwest_builder(
self,
client: &reqwest_middleware::ClientWithMiddleware,
base_url: &Url,
) -> std::result::Result<reqwest_middleware::RequestBuilder, ReqwestBuilderError> {
let url = construct_url(base_url, &self.endpoint());
let mut builder = client.request(self.method(), &url);
if let Some(params) = self.query_params() {
builder = builder.query(¶ms);
}
builder = self.add_body_to_builder(builder)?;
if let Some(headers) = self.headers() {
let header_map = serialize_to_header_map(&headers)?;
builder = builder.headers(header_map);
}
Ok(builder)
}
fn add_body_to_builder(
&self,
mut builder: reqwest_middleware::RequestBuilder,
) -> std::result::Result<reqwest_middleware::RequestBuilder, ReqwestBuilderError> {
match self.body() {
RequestBody::Json => {
let json_str = serde_json::to_string(self).map_err(ReqwestBuilderError::from)?;
if json_str != "{}" {
builder = builder.json(self);
}
}
RequestBody::Form => {
let params = serialize_to_form_params(self)?;
builder = builder.form(¶ms);
}
RequestBody::Multipart => {
if let Some(form) = self.create_multipart_form() {
builder = builder.multipart(form);
}
}
RequestBody::None => {
}
}
Ok(builder)
}
}
pub fn query_param_helper<T>(
value: &T,
param_name: &str,
params: &mut std::collections::HashMap<String, String>,
) where
T: QueryParamValue,
{
value.add_to_params(param_name, params);
}
pub trait QueryParamValue {
fn add_to_params(
&self,
param_name: &str,
params: &mut std::collections::HashMap<String, String>,
);
}
impl<T: std::fmt::Display> QueryParamValue for Option<T> {
fn add_to_params(
&self,
param_name: &str,
params: &mut std::collections::HashMap<String, String>,
) {
if let Some(value) = self {
params.insert(param_name.to_string(), value.to_string());
}
}
}
impl QueryParamValue for String {
fn add_to_params(
&self,
param_name: &str,
params: &mut std::collections::HashMap<String, String>,
) {
params.insert(param_name.to_string(), self.clone());
}
}
impl QueryParamValue for &str {
fn add_to_params(
&self,
param_name: &str,
params: &mut std::collections::HashMap<String, String>,
) {
params.insert(param_name.to_string(), self.to_string());
}
}
impl QueryParamValue for u32 {
fn add_to_params(
&self,
param_name: &str,
params: &mut std::collections::HashMap<String, String>,
) {
params.insert(param_name.to_string(), self.to_string());
}
}
impl QueryParamValue for u64 {
fn add_to_params(
&self,
param_name: &str,
params: &mut std::collections::HashMap<String, String>,
) {
params.insert(param_name.to_string(), self.to_string());
}
}
impl QueryParamValue for i32 {
fn add_to_params(
&self,
param_name: &str,
params: &mut std::collections::HashMap<String, String>,
) {
params.insert(param_name.to_string(), self.to_string());
}
}
impl QueryParamValue for i64 {
fn add_to_params(
&self,
param_name: &str,
params: &mut std::collections::HashMap<String, String>,
) {
params.insert(param_name.to_string(), self.to_string());
}
}
impl QueryParamValue for bool {
fn add_to_params(
&self,
param_name: &str,
params: &mut std::collections::HashMap<String, String>,
) {
params.insert(param_name.to_string(), self.to_string());
}
}