1use std::future::Future;
2use std::ops::{Deref, DerefMut};
3
4use reqwest::{Client as ReqwestClient, ClientBuilder, Request as ReqwestRequest};
5use salvo::http::header::CONTENT_TYPE;
6use salvo::http::{HeaderName, HeaderValue, Method};
7use serde::Deserialize;
8use thiserror::Error;
9use url::{ParseError, Url};
10
11pub fn client() -> ReqwestClient {
12 ClientBuilder::new().build().unwrap()
13}
14
15#[derive(Debug)]
16pub struct SendRequest {
17 inner: ReqwestRequest,
18}
19
20#[macro_export]
21macro_rules! json_body_modifier {
22 ($name:ident) => {
23 impl crate::sending::SendModifier for $name {
24 fn modify(self, request: &mut crate::sending::SendRequest) -> Result<(), crate::sending::SendError> {
25 let bytes = serde_json::to_vec(&self)?;
26 *request.body_mut() = Some(bytes.into());
27 Ok(())
28 }
29 }
30 };
31}
32macro_rules! method {
33 ($name:ident, $method:ident) => {
34 pub fn $name(url: Url) -> SendRequest {
35 SendRequest {
36 inner: ReqwestRequest::new(Method::$method, url),
37 }
38 }
39 };
40}
41method!(get, GET);
42method!(patch, PATCH);
43method!(put, PUT);
44method!(post, POST);
45method!(delete, DELETE);
46
47#[derive(Error, Debug)]
48pub enum SendError {
49 #[error("parse url: `{0}`")]
50 Url(#[from] ParseError),
51 #[error("reqwest: `{0}`")]
52 Reqwest(#[from] reqwest::Error),
53 #[error("json: `{0}`")]
54 Json(#[from] serde_json::Error),
55 #[error("other: `{0}`")]
56 Other(String),
57}
58
59impl SendError {
60 pub fn other(msg: impl Into<String>) -> Self {
61 Self::Other(msg.into())
62 }
63}
64
65pub type SendResult<T> = Result<T, SendError>;
66
67impl SendRequest {
68 method!(get, GET);
69 method!(patch, PATCH);
70 method!(put, PUT);
71 method!(post, POST);
72 method!(delete, DELETE);
73
74 pub fn into_inner(self) -> reqwest::Request {
75 self.inner
76 }
77 pub fn stuff(mut self, modifier: impl SendModifier) -> Result<Self, SendError> {
78 modifier.modify(&mut self)?;
79 if !self.headers().contains_key(CONTENT_TYPE) {
80 self.headers_mut()
81 .insert(CONTENT_TYPE, "application/json".parse().unwrap());
82 }
83 Ok(self)
84 }
85
86 pub async fn load<R>(self) -> Result<R, SendError>
87 where
88 R: for<'de> Deserialize<'de>,
89 {
90 let res = client().execute(self.inner).await?;
91 res.json().await.map_err(SendError::Reqwest)
92 }
93
94 pub async fn load_by_client<R>(self, client: ReqwestClient) -> Result<R, SendError>
95 where
96 R: for<'de> Deserialize<'de>,
97 {
98 let res = client.execute(self.inner).await?;
99 res.json().await.map_err(SendError::Reqwest)
100 }
101
102 pub async fn send<R>(self) -> Result<R, SendError>
103 where
104 R: for<'de> Deserialize<'de>,
105 {
106 let res = client().execute(self.inner).await?;
107 res.json().await.map_err(SendError::Reqwest)
108 }
109
110 pub async fn send_by_client<R>(self, client: ReqwestClient) -> Result<R, SendError>
111 where
112 R: for<'de> Deserialize<'de>,
113 {
114 let res = client.execute(self.inner).await?;
115 res.json().await.map_err(SendError::Reqwest)
116 }
117
118 pub fn exec(self) -> impl Future<Output = Result<reqwest::Response, reqwest::Error>> {
119 client().execute(self.inner)
120 }
121}
122
123impl Deref for SendRequest {
124 type Target = ReqwestRequest;
125 fn deref(&self) -> &Self::Target {
126 &self.inner
127 }
128}
129impl DerefMut for SendRequest {
130 fn deref_mut(&mut self) -> &mut Self::Target {
131 &mut self.inner
132 }
133}
134
135pub trait SendModifier {
136 fn modify(self, request: &mut SendRequest) -> Result<(), SendError>;
137}
138
139impl SendModifier for (HeaderName, HeaderValue) {
140 fn modify(self, request: &mut SendRequest) -> Result<(), SendError> {
141 request.headers_mut().append(self.0, self.1);
142 Ok(())
143 }
144}