Compare commits
No commits in common. "91dce87c88e24a828f5dac83c630e7b50de29b80" and "63f4975d5a3cbc841439f698a7cea85660fcb78e" have entirely different histories.
91dce87c88
...
63f4975d5a
@ -252,12 +252,7 @@ impl Manager for ManagerImpl {
|
|||||||
return Err(unexpected::Error::from("origin is proxy, can't serve file").into());
|
return Err(unexpected::Error::from("origin is proxy, can't serve file").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = settings.process_path(path);
|
let f = self.origin_store.get_file(&settings.origin_descr, path)?;
|
||||||
|
|
||||||
let f = self
|
|
||||||
.origin_store
|
|
||||||
.get_file(&settings.origin_descr, path.as_ref())?;
|
|
||||||
|
|
||||||
Ok(f)
|
Ok(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,23 @@
|
|||||||
use crate::error::unexpected::{self, Mappable};
|
use crate::error::unexpected::{self, Mappable};
|
||||||
use crate::origin;
|
use crate::origin;
|
||||||
|
|
||||||
use std::borrow;
|
|
||||||
|
|
||||||
use hex::ToHex;
|
use hex::ToHex;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "protocol")]
|
||||||
|
pub enum SettingsServeProtocol {
|
||||||
|
#[serde(rename = "http")]
|
||||||
|
Http,
|
||||||
|
#[serde(rename = "https")]
|
||||||
|
Https,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_serve_protocols() -> Vec<SettingsServeProtocol> {
|
||||||
|
vec![SettingsServeProtocol::Http, SettingsServeProtocol::Https]
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||||
/// Defines how a domain will behave when it is accessed. These are configured by the owner of the
|
/// Defines how a domain will behave when it is accessed. These are configured by the owner of the
|
||||||
/// domain during setup.
|
/// domain during setup.
|
||||||
@ -14,8 +25,8 @@ pub struct Settings {
|
|||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub origin_descr: origin::Descr,
|
pub origin_descr: origin::Descr,
|
||||||
|
|
||||||
pub remove_path_prefix: Option<String>,
|
#[serde(default = "default_serve_protocols")]
|
||||||
pub add_path_prefix: Option<String>,
|
pub serve_protocols: Vec<SettingsServeProtocol>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Settings {
|
impl Settings {
|
||||||
@ -24,23 +35,4 @@ impl Settings {
|
|||||||
serde_json::to_writer(&mut h, self).or_unexpected()?;
|
serde_json::to_writer(&mut h, self).or_unexpected()?;
|
||||||
Ok(h.finalize().encode_hex::<String>())
|
Ok(h.finalize().encode_hex::<String>())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_path<'a>(&self, path: &'a str) -> borrow::Cow<'a, str> {
|
|
||||||
let mut path = borrow::Cow::Borrowed(path);
|
|
||||||
|
|
||||||
if let Some(ref remove_path_prefix) = self.remove_path_prefix {
|
|
||||||
if path.starts_with(remove_path_prefix.as_str()) {
|
|
||||||
*path.to_mut() = path.strip_prefix(remove_path_prefix).unwrap().to_string();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(ref add_path_prefix) = self.add_path_prefix {
|
|
||||||
let mut prefixed_path = String::with_capacity(add_path_prefix.len() + path.len());
|
|
||||||
prefixed_path.push_str(add_path_prefix);
|
|
||||||
prefixed_path.push_str(path.as_ref());
|
|
||||||
*path.to_mut() = prefixed_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
path
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -181,8 +181,7 @@ mod tests {
|
|||||||
url: "bar".to_string(),
|
url: "bar".to_string(),
|
||||||
branch_name: "baz".to_string(),
|
branch_name: "baz".to_string(),
|
||||||
},
|
},
|
||||||
remove_path_prefix: None,
|
serve_protocols: vec![domain::SettingsServeProtocol::Http],
|
||||||
add_path_prefix: None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
@ -205,8 +204,7 @@ mod tests {
|
|||||||
url: "BAR".to_string(),
|
url: "BAR".to_string(),
|
||||||
branch_name: "BAZ".to_string(),
|
branch_name: "BAZ".to_string(),
|
||||||
},
|
},
|
||||||
remove_path_prefix: None,
|
serve_protocols: vec![],
|
||||||
add_path_prefix: None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
store.set(&domain, &new_settings).expect("set");
|
store.set(&domain, &new_settings).expect("set");
|
||||||
|
@ -30,7 +30,7 @@ pub async fn serve_http_request(
|
|||||||
mut req: hyper::Request<hyper::Body>,
|
mut req: hyper::Request<hyper::Body>,
|
||||||
req_is_https: bool,
|
req_is_https: bool,
|
||||||
) -> unexpected::Result<hyper::Response<hyper::Body>> {
|
) -> unexpected::Result<hyper::Response<hyper::Body>> {
|
||||||
let (url, request_http_headers) = if let origin::Descr::Proxy {
|
let (proxy_url, request_http_headers) = if let origin::Descr::Proxy {
|
||||||
ref url,
|
ref url,
|
||||||
ref request_http_headers,
|
ref request_http_headers,
|
||||||
} = settings.origin_descr
|
} = settings.origin_descr
|
||||||
@ -67,12 +67,12 @@ pub async fn serve_http_request(
|
|||||||
.insert("x-forwarded-proto", HeaderValue::from_static("https"));
|
.insert("x-forwarded-proto", HeaderValue::from_static("https"));
|
||||||
}
|
}
|
||||||
|
|
||||||
match hyper_reverse_proxy::call(client_ip, url, req).await {
|
match hyper_reverse_proxy::call(client_ip, proxy_url, req).await {
|
||||||
Ok(res) => Ok(res),
|
Ok(res) => Ok(res),
|
||||||
// ProxyError doesn't actually implement Error :facepalm: so we have to format the error
|
// ProxyError doesn't actually implement Error :facepalm: so we have to format the error
|
||||||
// manually
|
// manually
|
||||||
Err(e) => Err(unexpected::Error::from(
|
Err(e) => Err(unexpected::Error::from(
|
||||||
format!("error while proxying to {url}: {e:?}").as_str(),
|
format!("error while proxying to {proxy_url}: {e:?}").as_str(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,6 +177,18 @@ impl<'svc> Service {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let allowed = settings.serve_protocols.iter().any(|p| match p {
|
||||||
|
domain::SettingsServeProtocol::Http => !req_is_https,
|
||||||
|
domain::SettingsServeProtocol::Https => req_is_https,
|
||||||
|
});
|
||||||
|
|
||||||
|
if !allowed {
|
||||||
|
return self.render_error_page(
|
||||||
|
421,
|
||||||
|
"The requested protocol is not supported by this domain",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// if the domain is backed by a proxy then that is handled specially.
|
// if the domain is backed by a proxy then that is handled specially.
|
||||||
if let origin::Descr::Proxy { .. } = settings.origin_descr {
|
if let origin::Descr::Proxy { .. } = settings.origin_descr {
|
||||||
return origin::proxy::serve_http_request(&settings, client_ip, req, req_is_https)
|
return origin::proxy::serve_http_request(&settings, client_ip, req, req_is_https)
|
||||||
|
@ -1,9 +1,22 @@
|
|||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{de, Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{domain, error::unexpected, origin};
|
use crate::{domain, error::unexpected, origin};
|
||||||
|
|
||||||
|
fn deserialize_bool<'de, D>(deserializer: D) -> Result<bool, D::Error>
|
||||||
|
where
|
||||||
|
D: de::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let s: &str = de::Deserialize::deserialize(deserializer)?;
|
||||||
|
|
||||||
|
match s {
|
||||||
|
"true" => Ok(true),
|
||||||
|
"false" => Ok(false),
|
||||||
|
_ => Err(de::Error::unknown_variant(s, &["true", "false"])),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Default)]
|
#[derive(Serialize, Deserialize, Default)]
|
||||||
pub struct FlatDomainSettings {
|
pub struct FlatDomainSettings {
|
||||||
domain_setting_origin_descr_kind: String,
|
domain_setting_origin_descr_kind: String,
|
||||||
@ -12,6 +25,14 @@ pub struct FlatDomainSettings {
|
|||||||
domain_setting_origin_descr_git_branch_name: Option<String>,
|
domain_setting_origin_descr_git_branch_name: Option<String>,
|
||||||
|
|
||||||
domain_setting_origin_descr_proxy_url: Option<String>,
|
domain_setting_origin_descr_proxy_url: Option<String>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
#[serde(deserialize_with = "deserialize_bool")]
|
||||||
|
domain_setting_serve_protocol_http: bool,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
#[serde(deserialize_with = "deserialize_bool")]
|
||||||
|
domain_setting_serve_protocol_https: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<FlatDomainSettings> for domain::Settings {
|
impl TryFrom<FlatDomainSettings> for domain::Settings {
|
||||||
@ -31,10 +52,19 @@ impl TryFrom<FlatDomainSettings> for domain::Settings {
|
|||||||
_ => Err("invalid domain_setting_origin_descr_kind".to_string()),
|
_ => Err("invalid domain_setting_origin_descr_kind".to_string()),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
let mut serve_protocols = Vec::<domain::SettingsServeProtocol>::default();
|
||||||
|
|
||||||
|
if v.domain_setting_serve_protocol_http {
|
||||||
|
serve_protocols.push(domain::SettingsServeProtocol::Http);
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.domain_setting_serve_protocol_https {
|
||||||
|
serve_protocols.push(domain::SettingsServeProtocol::Https);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
origin_descr,
|
origin_descr,
|
||||||
remove_path_prefix: None,
|
serve_protocols,
|
||||||
add_path_prefix: None,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,6 +88,17 @@ impl TryFrom<domain::Settings> for FlatDomainSettings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for serve_protocol in v.serve_protocols {
|
||||||
|
match serve_protocol {
|
||||||
|
domain::SettingsServeProtocol::Http => {
|
||||||
|
res.domain_setting_serve_protocol_http = true
|
||||||
|
}
|
||||||
|
domain::SettingsServeProtocol::Https => {
|
||||||
|
res.domain_setting_serve_protocol_https = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user