openid_client/types/
http_client.rs1use std::collections::HashMap;
4use std::fmt::Debug;
5use std::future;
6
7use url::Url;
8
9use crate::helpers::string_map_to_form_url_encoded;
10
11#[derive(Debug, Default, Clone)]
13#[cfg_attr(test, derive(PartialEq))]
14pub enum HttpMethod {
15 #[default]
17 GET,
18 POST,
20 PUT,
22 PATCH,
24 DELETE,
26 HEAD,
28 OPTIONS,
30 TRACE,
32 CONNECT,
34}
35
36#[derive(Debug, Clone, Copy)]
38pub struct HttpResponseExpectations {
39 pub body: bool,
41 pub bearer: bool,
43 pub json_body: bool,
45 pub status_code: u16,
47}
48
49#[derive(Debug)]
51pub struct ClientCertificate {
52 pub cert: String,
54 pub key: String,
56}
57
58#[derive(Debug)]
61pub struct HttpRequest {
62 pub url: Url,
64 pub method: HttpMethod,
66 pub headers: HashMap<String, Vec<String>>,
68 pub body: Option<String>,
70 pub mtls: bool,
72 pub client_certificate: Option<ClientCertificate>,
74 pub(crate) expectations: HttpResponseExpectations,
76}
77
78impl HttpRequest {
79 pub(crate) fn new() -> Self {
80 Self {
81 url: Url::parse("about:blank").unwrap(),
82
83 headers: HashMap::new(),
84 method: HttpMethod::GET,
85 body: None,
86 client_certificate: None,
87 mtls: false,
88 expectations: HttpResponseExpectations {
89 body: true,
90 bearer: false,
91 status_code: 200,
92 json_body: true,
93 },
94 }
95 }
96
97 pub(crate) fn url(mut self, url: Url) -> Self {
98 self.url = url;
99 self
100 }
101
102 pub(crate) fn method(mut self, method: HttpMethod) -> Self {
103 self.method = method;
104 self
105 }
106
107 pub(crate) fn header(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
108 let name = name.into();
109 let value = value.into();
110
111 if let Some(values) = self.headers.get_mut(&name) {
112 values.push(value);
113 } else {
114 let values = vec![value];
115 self.headers.insert(name, values);
116 }
117 self
118 }
119
120 pub(crate) fn header_replace(mut self, name: impl Into<String>, value: Vec<String>) -> Self {
121 self.headers.insert(name.into(), value);
122 self
123 }
124
125 pub(crate) fn headers(mut self, headers: HashMap<String, Vec<String>>) -> Self {
126 self.headers = headers;
127 self
128 }
129
130 pub(crate) fn json(mut self, json: String) -> Self {
131 self.headers.insert(
132 "content-type".to_string(),
133 vec!["application/json".to_string()],
134 );
135 self.body(json)
136 }
137
138 pub(crate) fn form(mut self, form: HashMap<String, String>) -> Self {
139 let form_body = string_map_to_form_url_encoded(&form).unwrap();
140 self.headers.insert(
141 "content-type".to_string(),
142 vec!["application/x-www-form-urlencoded".to_string()],
143 );
144 self.body(form_body)
145 }
146
147 pub(crate) fn body(mut self, body: String) -> Self {
148 self.headers
149 .insert("content-length".to_string(), vec![body.len().to_string()]);
150 self.body = Some(body);
151 self
152 }
153
154 pub(crate) fn mtls(mut self, mtls: bool) -> Self {
155 self.mtls = mtls;
156 self
157 }
158
159 pub(crate) fn expect_body(mut self, expect: bool) -> Self {
160 self.expectations.body = expect;
161 self
162 }
163
164 pub(crate) fn expect_status_code(mut self, code: u16) -> Self {
165 self.expectations.status_code = code;
166 self
167 }
168
169 pub(crate) fn expect_json_body(mut self, expect: bool) -> Self {
170 self.expectations.json_body = expect;
171 self
172 }
173
174 pub(crate) fn expect_bearer(mut self, bearer: bool) -> Self {
175 self.expectations.bearer = bearer;
176 self
177 }
178}
179
180#[derive(Debug, Clone)]
182pub struct HttpResponse {
183 pub status_code: u16,
185 pub content_type: Option<String>,
187 pub www_authenticate: Option<String>,
189 pub dpop_nonce: Option<String>,
191 pub body: Option<String>,
193}
194
195pub trait OidcHttpClient {
198 fn get_client_certificate(
200 &self,
201 _req: &HttpRequest,
202 ) -> impl std::future::Future<Output = Option<ClientCertificate>> + Send {
203 future::ready(None)
204 }
205
206 fn request(
217 &self,
218 req: HttpRequest,
219 ) -> impl std::future::Future<Output = Result<HttpResponse, String>> + Send;
220}