use anyhow::{Context, Result};
use reqwest::{
Body, Method, Request,
header::{HeaderName, HeaderValue},
};
use reqwest_middleware::{ClientWithMiddleware, RequestBuilder};
use serde::Serialize;
use std::collections::HashMap;
use std::fmt::Display;
pub trait ApiInterface: Send + Sync {
fn build_request<
E: Display,
HK: Into<HeaderName>,
HV: Into<HeaderValue>,
P: Serialize,
B: Serialize,
>(
&self,
client: ClientWithMiddleware,
endpoint: E,
method: Method,
headers: HashMap<HK, HV>,
params: Option<P>,
body: Option<B>,
) -> Result<Request> {
let url = format!("{}{endpoint}", self.get_base_url());
let request = Request::new(method, url.parse()?);
let mut builder = RequestBuilder::from_parts(client, request);
builder = builder.headers(
headers
.into_iter()
.map(|(k, v)| (k.into(), v.into()))
.collect(),
);
builder = self.get_auth_info(builder);
if let Some(params) = params {
builder = builder.query(¶ms);
}
if let Some(body) = body {
let body = serde_json::to_string(&body)?;
builder = builder.body(Body::from(body));
}
builder = self.additional_modifications(builder);
builder
.build()
.context("Cannot build request inside ApiInterface")
}
fn get_base_url(&self) -> String;
fn get_auth_info(&self, request: RequestBuilder) -> RequestBuilder;
fn additional_modifications(&self, request: RequestBuilder) -> RequestBuilder {
request
}
}