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.insert(
149 "content-length".to_string(),
150 vec![body.as_bytes().len().to_string()],
151 );
152 self.body = Some(body);
153 self
154 }
155
156 pub(crate) fn mtls(mut self, mtls: bool) -> Self {
157 self.mtls = mtls;
158 self
159 }
160
161 pub(crate) fn expect_body(mut self, expect: bool) -> Self {
162 self.expectations.body = expect;
163 self
164 }
165
166 pub(crate) fn expect_status_code(mut self, code: u16) -> Self {
167 self.expectations.status_code = code;
168 self
169 }
170
171 pub(crate) fn expect_json_body(mut self, expect: bool) -> Self {
172 self.expectations.json_body = expect;
173 self
174 }
175
176 pub(crate) fn expect_bearer(mut self, bearer: bool) -> Self {
177 self.expectations.bearer = bearer;
178 self
179 }
180}
181
182#[derive(Debug, Clone)]
184pub struct HttpResponse {
185 pub status_code: u16,
187 pub content_type: Option<String>,
189 pub www_authenticate: Option<String>,
191 pub dpop_nonce: Option<String>,
193 pub body: Option<String>,
195}
196
197pub trait OidcHttpClient {
200 fn get_client_certificate(
202 &self,
203 _req: &HttpRequest,
204 ) -> impl std::future::Future<Output = Option<ClientCertificate>> + Send {
205 future::ready(None)
206 }
207
208 fn request(
219 &self,
220 req: HttpRequest,
221 ) -> impl std::future::Future<Output = Result<HttpResponse, String>> + Send;
222}