use crate::config::advanced::HttpClient;
use crate::error::Error;
use crate::error::Result;
use crate::http::client::HttpClientConfig;
use crate::storage;
#[cfg(feature = "experimental")]
use crate::storage::c4gh::C4GHKeys;
use cfg_if::cfg_if;
use http::Uri;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(JsonSchema, Serialize, Deserialize, Debug, Clone)]
#[serde(default, deny_unknown_fields)]
pub struct Url {
#[schemars(with = "String")]
#[serde(with = "http_serde::uri")]
url: Uri,
#[schemars(with = "Option::<String>")]
#[serde(with = "http_serde::option::uri")]
response_url: Option<Uri>,
allow_headers_backend: Vec<String>,
deny_headers_backend: Vec<String>,
allow_headers_client: Vec<String>,
deny_headers_client: Vec<String>,
#[schemars(skip)]
#[serde(alias = "tls", skip_serializing)]
http: HttpClientConfig,
#[cfg(feature = "experimental")]
#[serde(skip_serializing)]
keys: Option<C4GHKeys>,
#[cfg(feature = "experimental")]
forward_public_key: bool,
#[serde(skip)]
pub(crate) is_defaulted: bool,
}
impl Url {
pub fn new(
url: Uri,
response_url: Option<Uri>,
allow_headers_backend: Vec<String>,
deny_headers_backend: Vec<String>,
allow_headers_client: Vec<String>,
deny_headers_client: Vec<String>,
http: HttpClientConfig,
) -> Self {
Self {
url,
response_url,
allow_headers_backend,
deny_headers_backend,
allow_headers_client,
deny_headers_client,
http,
#[cfg(feature = "experimental")]
keys: None,
is_defaulted: false,
#[cfg(feature = "experimental")]
forward_public_key: true,
}
}
pub fn url(&self) -> &Uri {
&self.url
}
pub fn response_url(&self) -> Option<&Uri> {
self.response_url.as_ref()
}
pub fn allow_headers_backend(&self) -> &[String] {
&self.allow_headers_backend
}
pub fn deny_headers_backend(&self) -> &[String] {
&self.deny_headers_backend
}
pub fn allow_headers_client(&self) -> &[String] {
&self.allow_headers_client
}
pub fn deny_headers_client(&self) -> &[String] {
&self.deny_headers_client
}
pub fn http(&self) -> &HttpClientConfig {
&self.http
}
#[cfg(feature = "experimental")]
pub fn set_keys(mut self, keys: Option<C4GHKeys>) -> Self {
self.keys = keys;
self
}
#[cfg(feature = "experimental")]
pub fn keys(&self) -> Option<&C4GHKeys> {
self.keys.as_ref()
}
#[cfg(feature = "experimental")]
pub fn set_forward_public_key(&mut self, forward_public_key: bool) {
self.forward_public_key = forward_public_key;
}
#[cfg(feature = "experimental")]
pub fn forward_public_key(&self) -> bool {
self.forward_public_key
}
}
impl TryFrom<Url> for storage::url::Url {
type Error = Error;
fn try_from(storage: Url) -> Result<Self> {
let client = HttpClient::from(storage.http);
let url_storage = Self::new(
storage.url.clone(),
storage.response_url.unwrap_or(storage.url),
storage.allow_headers_backend,
storage.deny_headers_backend,
storage.allow_headers_client,
storage.deny_headers_client,
client,
);
cfg_if! {
if #[cfg(feature = "experimental")] {
let mut url_storage = url_storage;
url_storage.set_keys(storage.keys);
url_storage.set_forward_public_key(storage.forward_public_key);
Ok(url_storage)
} else {
Ok(url_storage)
}
}
}
}
impl Default for Url {
fn default() -> Self {
let mut url = Self::new(
Default::default(),
Default::default(),
vec!["*".to_string()],
vec![],
vec!["*".to_string()],
vec![],
Default::default(),
);
url.is_defaulted = true;
url
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::config::tests::test_serialize_and_deserialize;
#[test]
fn url_backend() {
test_serialize_and_deserialize(
r#"
url = "https://example.com"
response_url = "https://example.com"
allow_headers_backend = ["Authorization"]
deny_headers_backend = ["X-Internal-*"]
allow_headers_client = ["Authorization"]
deny_headers_client = ["X-Internal-*"]
"#,
(
"https://example.com/".to_string(),
"https://example.com/".to_string(),
vec!["Authorization".to_string()],
vec!["X-Internal-*".to_string()],
vec!["Authorization".to_string()],
vec!["X-Internal-*".to_string()],
),
|result: Url| {
(
result.url().to_string(),
result.response_url().unwrap().to_string(),
result.allow_headers_backend,
result.deny_headers_backend,
result.allow_headers_client,
result.deny_headers_client,
)
},
);
}
}