inth_oauth2_async/client/
http_client.rs1use crate::client::error::ClientError;
8
9#[async_trait::async_trait]
11pub trait HttpClient {
12 async fn post(
22 &self,
23 url: &str,
24 client_id: &str,
25 client_secret: &str,
26 body: String,
27 ) -> Result<serde_json::Value, ClientError>;
28}
29
30#[cfg(feature = "reqwest-client")]
32pub mod reqwest_client {
33 use super::*;
34 use reqwest::header::{ACCEPT, CONTENT_TYPE};
35
36 #[async_trait::async_trait]
37 impl HttpClient for reqwest::Client {
38 async fn post(
39 &self,
40 url: &str,
41 client_id: &str,
42 client_secret: &str,
43 body: String,
44 ) -> Result<serde_json::Value, ClientError> {
45 let response = reqwest::Client::post(self, url)
46 .basic_auth(client_id, Some(client_secret))
47 .header(ACCEPT, "application/json")
48 .header(CONTENT_TYPE, "application/x-www-form-urlencoded")
49 .body(body)
50 .send()
51 .await?;
52
53 let full = response.bytes().await?;
54 let json = serde_json::from_slice(&full)?;
55
56 Ok(json)
57 }
58 }
59}
60
61#[cfg(feature = "hyper-client")]
63pub mod hyper_client {
64 use super::*;
65 use base64::write::EncoderWriter as Base64Encoder;
66 use http_body_util::BodyExt;
67 use hyper::body::Body;
68 use hyper::header::{AUTHORIZATION, ACCEPT, CONTENT_TYPE, HeaderValue};
69 use hyper::Request;
70 use hyper_util::client::legacy::connect::Connect;
71 use std::io::Write;
72
73 #[async_trait::async_trait]
74 impl<C, B> HttpClient for hyper_util::client::legacy::Client<C, B> where
75 C: Connect + Clone + Send + Sync + 'static,
77 B: Body + From<String> + Send + Unpin + 'static,
78 B::Data: Send,
79 B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
80 {
81 async fn post(
82 &self,
83 url: &str,
84 client_id: &str,
85 client_secret: &str,
86 body: String,
87 ) -> Result<serde_json::Value, ClientError> {
88 let mut auth_header = b"Basic ".to_vec();
89 {
90 let mut enc = Base64Encoder::new(&mut auth_header, base64::STANDARD);
91 write!(enc, "{}:{}", client_id, client_secret)?;
92 }
93
94 let mut auth_header_val = HeaderValue::from_bytes(&auth_header)
95 .expect("invalid header value"); auth_header_val.set_sensitive(true);
97
98 let req = Request::post(url)
99 .header(AUTHORIZATION, auth_header_val)
100 .header(ACCEPT, "application/json")
101 .header(CONTENT_TYPE, "application/x-www-form-urlencoded")
102 .body(body.into())?;
103
104 let response = self.request(req).await?;
105 let full = response.into_body().collect().await?.to_bytes();
106 let json = serde_json::from_slice(&full)?;
107 Ok(json)
108 }
109 }
110}