1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
use std::{collections::HashMap, time::Duration};
use reqwest::{header::HeaderMap, Method, StatusCode};
// TODO: enrich request options with agent, ca, cert, crl, headers, key, lookup, passphrase, pfx, timeout. (refer panva doc)
/// # Request Interceptor
/// `RequestInterceptor` is the alias for the closure that will be executed
/// every time a request is being made.
pub type RequestInterceptor = Box<dyn FnMut(&Request) -> RequestOptions>;
/// # Request
/// Request is an internal struct used to create various OIDC requests.
#[derive(Debug)]
pub struct Request {
/// Url of the request without query params
pub url: String,
/// Expected status code from the server
pub expected: StatusCode,
/// Http method of the request
pub method: Method,
/// Whether or not to expect body with the response
pub expect_body: bool,
/// Specifies if the request is using bearer auth, and checks for bearer token related errors
pub bearer: bool,
/// Headers that are sent in the request
pub headers: HeaderMap,
/// Query Params that are send with the request
pub search_params: HashMap<String, Vec<String>>,
/// The request body to be sent
pub json: Option<serde_json::Value>,
/// Expected response type
pub response_type: Option<String>,
}
impl Default for Request {
fn default() -> Self {
Self {
expect_body: true,
bearer: false,
expected: StatusCode::OK,
headers: HeaderMap::default(),
method: Method::GET,
url: "".to_string(),
search_params: HashMap::new(),
json: None,
response_type: None,
}
}
}
impl Request {
/// Converts `search_params` to a [reqwest] compatible query params format
pub(crate) fn get_reqwest_query(&self) -> Vec<(String, String)> {
let mut query_list: Vec<(String, String)> = vec![];
for (k, v) in &self.search_params {
for val in v {
query_list.push((k.clone(), val.to_string()))
}
}
query_list
}
}
/// # Response
/// Response is the abstracted version of the [reqwest] Response (async and blocking).
#[derive(Debug, Clone)]
pub struct Response {
/// Body from the response
pub body: Option<String>,
/// Status code of the response
pub status: StatusCode,
/// Response headers from the server
pub headers: HeaderMap,
}
impl Response {
/// Creates a new instance of Response from [reqwest::blocking::Response]
pub(crate) fn from(response: reqwest::blocking::Response) -> Self {
let status = response.status();
let headers = response.headers().clone();
let body_result = response.text();
let mut body: Option<String> = None;
if let Ok(body_string) = body_result {
if !body_string.is_empty() {
body = Some(body_string);
}
}
Self {
body,
status,
headers,
}
}
/// Creates a new instance of Response from [reqwest::Response]
pub(crate) async fn from_async(response: reqwest::Response) -> Self {
let status = response.status();
let headers = response.headers().clone();
let body_result = response.text().await;
let mut body: Option<String> = None;
if let Ok(body_string) = body_result {
if !body_string.is_empty() {
body = Some(body_string);
}
}
Self {
body,
status,
headers,
}
}
}
/// # RequestOptions
/// This struct is the return type of the request interceptor that can be passed to various methods
/// such as:
/// 1. [`crate::issuer::Issuer::webfinger_async()`]
/// 2. [`crate::issuer::Issuer::webfinger()`]
/// 3. [`crate::issuer::Issuer::discover_async()`]
/// 4. [`crate::issuer::Issuer::discover()`]
/// 5. [`crate::client::Client::from_uri()`]
/// 6. [`crate::client::Client::from_uri_async()`]
/// 7. [`crate::client::Client::register()`]
/// 8. [`crate::client::Client::register_async()`]
#[derive(Debug)]
pub struct RequestOptions {
/// Headers that are tobe appended with the request that is going to be made
pub headers: HeaderMap,
/// Request timeout
pub timeout: Duration,
}