1use std::{convert::TryFrom, marker::PhantomData};
2
3use crate::reqwest::{Client, RequestBuilder as ReqwestRequestBuilder};
4use ::reqwest::header::{HeaderName, HeaderValue};
5use ajars_core::{HttpMethod, RestType};
6use http::HeaderMap;
7use serde::{de::DeserializeOwned, Serialize};
8
9pub mod reqwest {
10 pub use reqwest::*;
11}
12
13#[derive(Clone)]
14pub struct AjarsReqwest {
15 client: Client,
16 base_url: String,
17}
18
19impl AjarsReqwest {
20 pub fn new<S: Into<String>>(client: Client, base_url: S) -> Self {
21 Self { client, base_url: base_url.into() }
22 }
23
24 pub fn request<'a, I: Serialize + DeserializeOwned, O: Serialize + DeserializeOwned, REST: RestType<I, O>>(
25 &self,
26 rest: &'a REST,
27 ) -> RequestBuilder<'a, I, O, REST> {
28 let url = format!("{}{}", &self.base_url, rest.path());
29
30 let request = match rest.method() {
31 HttpMethod::DELETE => self.client.delete(&url),
32 HttpMethod::GET => self.client.get(&url),
33 HttpMethod::POST => self.client.post(&url),
34 HttpMethod::PUT => self.client.put(&url),
35 };
36
37 RequestBuilder { rest, request, phantom_i: PhantomData, phantom_o: PhantomData }
38 }
39}
40
41pub struct RequestBuilder<'a, I: Serialize + DeserializeOwned, O: Serialize + DeserializeOwned, REST: RestType<I, O>> {
42 rest: &'a REST,
43 request: ReqwestRequestBuilder,
44 phantom_i: PhantomData<I>,
45 phantom_o: PhantomData<O>,
46}
47
48impl<'a, I: Serialize + DeserializeOwned, O: Serialize + DeserializeOwned, REST: RestType<I, O>>
49 RequestBuilder<'a, I, O, REST>
50{
51 pub async fn send(self, data: &I) -> Result<O, reqwest::Error> {
54 let request = match self.rest.method() {
55 HttpMethod::DELETE | HttpMethod::GET => self.request.query(data),
56 HttpMethod::POST | HttpMethod::PUT => self.request.header("Content-Type", "application/json").json(data),
57 };
58
59 request.send().await?.json().await
60 }
61
62 pub fn header<K, V>(mut self, key: K, value: V) -> Self
64 where
65 HeaderName: TryFrom<K>,
66 <HeaderName as TryFrom<K>>::Error: Into<http::Error>,
67 HeaderValue: TryFrom<V>,
68 <HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
69 {
70 self.request = self.request.header(key, value);
71 self
72 }
73
74 pub fn headers(mut self, headers: HeaderMap) -> Self {
78 self.request = self.request.headers(headers);
79 self
80 }
81
82 #[cfg(not(target_arch = "wasm32"))]
83 pub fn basic_auth<U, P>(mut self, username: U, password: Option<P>) -> Self
85 where
86 U: std::fmt::Display,
87 P: std::fmt::Display,
88 {
89 self.request = self.request.basic_auth(username, password);
90 self
91 }
92
93 pub fn bearer_auth<T>(mut self, token: T) -> Self
95 where
96 T: std::fmt::Display,
97 {
98 self.request = self.request.bearer_auth(token);
99 self
100 }
101
102 #[cfg(not(target_arch = "wasm32"))]
103 pub fn timeout(mut self, timeout: std::time::Duration) -> Self {
109 self.request = self.request.timeout(timeout);
110 self
111 }
112}