openid_client/
http_client.rs1use std::time::Duration;
4
5use reqwest::{
6 header::{CONTENT_TYPE, WWW_AUTHENTICATE},
7 ClientBuilder, Method, Response,
8};
9
10use crate::types::http_client::{HttpMethod, HttpRequest, HttpResponse, OidcHttpClient};
11
12pub struct DefaultHttpClient;
14
15impl DefaultHttpClient {
16 async fn to_response(response: Response) -> HttpResponse {
17 let status_code = response.status().as_u16();
18 let response_headers = response.headers().clone();
19
20 let mut content_type = None;
21
22 if let Some(Ok(ct)) = response_headers
23 .get(CONTENT_TYPE)
24 .map(|ct| ct.to_str().map(|s| s.to_string()))
25 {
26 content_type = Some(ct);
27 };
28
29 let mut www_authenticate = None;
30
31 if let Some(Ok(www)) = response_headers
32 .get(WWW_AUTHENTICATE)
33 .map(|www| www.to_str().map(|s| s.to_string()))
34 {
35 www_authenticate = Some(www);
36 };
37
38 let mut dpop_nonce = None;
39
40 if let Some(Ok(dn)) = response_headers
41 .get("dpop-nonce")
42 .map(|dn| dn.to_str().map(|s| s.to_string()))
43 {
44 dpop_nonce = Some(dn);
45 };
46
47 let body_result = response.text().await;
48 let mut body: Option<String> = None;
49 if let Ok(body_string) = body_result {
50 if !body_string.is_empty() {
51 body = Some(body_string);
52 }
53 }
54
55 HttpResponse {
56 body,
57 status_code,
58 content_type,
59 www_authenticate,
60 dpop_nonce,
61 }
62 }
63}
64
65impl OidcHttpClient for DefaultHttpClient {
66 async fn request(&self, req: HttpRequest) -> Result<HttpResponse, String> {
67 let client = ClientBuilder::new()
68 .connect_timeout(Duration::from_secs(10))
69 .build()
70 .map_err(|e| format!("{e}"))?;
71
72 let method = match req.method {
73 HttpMethod::GET => Method::GET,
74 HttpMethod::POST => Method::POST,
75 HttpMethod::PUT => Method::PUT,
76 HttpMethod::PATCH => Method::PATCH,
77 HttpMethod::DELETE => Method::DELETE,
78 HttpMethod::HEAD => Method::HEAD,
79 HttpMethod::OPTIONS => Method::OPTIONS,
80 HttpMethod::TRACE => Method::TRACE,
81 HttpMethod::CONNECT => Method::CONNECT,
82 };
83
84 let mut req_builder = client.request(method, req.url);
85
86 if let Some(body) = req.body {
87 req_builder = req_builder.body(body);
88 }
89
90 for (name, values) in req.headers {
91 for value in values {
92 req_builder = req_builder.header(name.clone(), value);
93 }
94 }
95
96 req_builder = req_builder.header(
97 "User-Agent",
98 "openid-client (https://github.com/sathyajithps/openid-client)",
99 );
100
101 match req_builder.send().await {
102 Ok(res) => Ok(Self::to_response(res).await),
103 Err(e) => Err(format!("{e}")),
104 }
105 }
106}