use std::borrow::Borrow;
use crate::{ServerError, WechatError};
#[cfg(feature = "multipart")]
use reqwest::multipart;
use reqwest::{IntoUrl, Url};
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
pub trait ClientTrait {
fn access_token(&self) -> impl Future<Output = crate::Result<String>> + Send;
fn refresh_access_token(&mut self) -> impl Future<Output = crate::Result<()>> + Send;
fn http_client(&self) -> &reqwest::Client;
fn url_with_query<I, K, V>(&self, url: &str, queries: I) -> crate::Result<Url>
where
I: IntoIterator,
I::Item: Borrow<(K, V)>,
K: AsRef<str>,
V: AsRef<str>,
{
Ok(
Url::parse_with_params(url, queries)
.map_err(|err| WechatError::CommonError(err.to_string()))?,
)
}
fn authorized_url(&self, url: &str) -> impl Future<Output = crate::Result<Url>> + Send
where
Self: Sync,
{
async {
let access_token = self.access_token().await?;
self.url_with_query(url, &[("access_token", access_token)])
}
}
fn get_empty<R: DeserializeOwned, U: IntoUrl + Send, >(
&self,
url: U,
) -> impl Future<Output = crate::Result<R>> + Send
where
Self: Sync,
{
async {
Ok(self
.http_client()
.get(url)
.send()
.await?
.json::<R>()
.await?)
}
}
fn get<R: DeserializeOwned, U: IntoUrl + Send, T: Serialize + ?Sized + Sync>(
&self,
url: U,
query: &T,
) -> impl Future<Output = crate::Result<R>> + Send
where
Self: Sync,
{
async {
Ok(self
.http_client()
.get(url)
.query(query)
.send()
.await?
.json::<R>()
.await?)
}
}
fn post_empty<R: DeserializeOwned, U: IntoUrl + Send>(
&self,
url: U,
) -> impl Future<Output = crate::Result<R>> + Send
where
Self: Sync,
{
async {
Ok(self
.http_client()
.post(url)
.send()
.await?
.json::<R>()
.await?)
}
}
fn post<R: DeserializeOwned, U: IntoUrl + Send, T: Serialize + ?Sized + Sync>(
&self,
url: U,
data: &T,
) -> impl Future<Output = crate::Result<R>> + Send
where
Self: Sync,
{
async {
Ok(self
.http_client()
.post(url)
.form(data)
.send()
.await?
.json::<R>()
.await?)
}
}
#[cfg(feature = "multipart")]
fn upload<R: DeserializeOwned, U: IntoUrl + Send>(
&self,
url: U,
multipart: multipart::Form,
) -> impl Future<Output = crate::Result<R>> + Send
where
Self: Sync,
{
async {
Ok(self
.http_client()
.post(url)
.multipart(multipart)
.send()
.await?
.json::<R>()
.await?)
}
}
#[cfg(feature = "multipart")]
fn upload_with<R: DeserializeOwned, U: IntoUrl + Send, T: Serialize + ?Sized + Sync>(
&self,
url: U,
data: &T,
multipart: multipart::Form,
) -> impl Future<Output = crate::Result<R>> + Send
where
Self: Sync,
{
async {
Ok(self
.http_client()
.post(url)
.form(data)
.multipart(multipart)
.send()
.await?
.json::<R>()
.await?)
}
}
fn json<R: DeserializeOwned, U: IntoUrl + Send, T: Serialize + ?Sized + Sync>(
&self,
url: U,
data: &T,
) -> impl Future<Output = crate::Result<R>> + Send
where
Self: Sync,
{
async {
Ok(self
.http_client()
.post(url)
.json(data)
.send()
.await?
.json::<R>()
.await?)
}
}
fn download<U: IntoUrl + Send, T: Serialize + ?Sized + Sync>(
&self,
url: U,
query: &T,
) -> impl Future<Output = crate::Result<Vec<u8>>> + Send
where
Self: Sync,
{
async {
let response = self
.http_client()
.get(url)
.query(query)
.send()
.await?;
if response.status() == 200 {
Ok(response.bytes().await?.to_vec())
} else {
let res: ServerError = response.json().await?;
Err(WechatError::ServerError(res))
}
}
}
}