Support website publishing #7

Merged
lx merged 61 commits from feature/website into master 2021-01-15 16:49:51 +00:00
4 changed files with 54 additions and 6 deletions
Showing only changes of commit 4093833ae8 - Show all commits

1
Cargo.lock generated
View file

@ -661,6 +661,7 @@ dependencies = [
"http", "http",
"hyper", "hyper",
"log", "log",
"percent-encoding",
"rand", "rand",
"rmp-serde", "rmp-serde",
"roxmltree", "roxmltree",

View file

@ -54,7 +54,8 @@ pub struct ApiConfig {
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
pub struct WebConfig { pub struct WebConfig {
pub web_bind_addr: SocketAddr, pub bind_addr: SocketAddr,
pub root_domain: String,
} }
fn default_max_concurrent_rpc_requests() -> usize { fn default_max_concurrent_rpc_requests() -> usize {

View file

@ -36,6 +36,7 @@ tokio = { version = "0.2", default-features = false, features = ["rt-core", "rt-
http = "0.2" http = "0.2"
hyper = "0.13" hyper = "0.13"
percent-encoding = "2.1.0"
rustls = "0.17" rustls = "0.17"
webpki = "0.21" webpki = "0.21"

View file

@ -15,7 +15,7 @@ pub async fn run_web_server(
garage: Arc<Garage>, garage: Arc<Garage>,
shutdown_signal: impl Future<Output = ()>, shutdown_signal: impl Future<Output = ()>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let addr = &garage.config.s3_web.web_bind_addr; let addr = &garage.config.s3_web.bind_addr;
let service = make_service_fn(|conn: &AddrStream| { let service = make_service_fn(|conn: &AddrStream| {
let garage = garage.clone(); let garage = garage.clone();
@ -43,17 +43,23 @@ async fn handler(
addr: SocketAddr, addr: SocketAddr,
) -> Result<Response<Body>, Error> { ) -> Result<Response<Body>, Error> {
// Get http authority string (eg. [::1]:3902) // Get http authority string (eg. [::1]:3902 or garage.tld:80)
let authority = req let authority = req
.headers() .headers()
.get(HOST) .get(HOST)
.ok_or(Error::BadRequest(format!("HOST header required")))? .ok_or(Error::BadRequest(format!("HOST header required")))?
.to_str()?; .to_str()?;
info!("authority is {}", authority);
// Get HTTP domain/ip from host // Get bucket
let host = authority_to_host(authority)?; let host = authority_to_host(authority)?;
info!("host is {}", host); let root = &garage.config.s3_web.root_domain;
let bucket = host_to_bucket(&host, root);
// Get path
let path = req.uri().path().to_string();
let key = percent_encoding::percent_decode_str(&path).decode_utf8()?;
info!("host: {}, bucket: {}, key: {}", host, bucket, key);
Ok(Response::new(Body::from("hello world\n"))) Ok(Response::new(Body::from("hello world\n")))
} }
@ -81,6 +87,18 @@ fn authority_to_host(authority: &str) -> Result<String, Error> {
} }
} }
fn host_to_bucket<'a>(host: &'a str, root: &str) -> &'a str {
if root.len() >= host.len() || !host.ends_with(root) {
return host;
quentin marked this conversation as resolved
Review

Rewrite as only two cases:

BucketState::Present(params) if params.website.get() => Ok(()),
_ => Err(Error::NotFound),
Rewrite as only two cases: ``` BucketState::Present(params) if params.website.get() => Ok(()), _ => Err(Error::NotFound), ```
}
let len_diff = host.len() - root.len();
let missing_starting_dot = root.chars().next() != Some('.');
let cursor = if missing_starting_dot { len_diff - 1 } else { len_diff };
&host[..cursor]
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
@ -107,4 +125,31 @@ mod tests {
assert_eq!(domain3, "127.0.0.1"); assert_eq!(domain3, "127.0.0.1");
Ok(()) Ok(())
} }
#[test]
fn host_to_bucket_test() {
assert_eq!(
host_to_bucket("john.doe.garage.tld", ".garage.tld"),
"john.doe");
assert_eq!(
host_to_bucket("john.doe.garage.tld", "garage.tld"),
"john.doe");
assert_eq!(
host_to_bucket("john.doe.com", "garage.tld"),
"john.doe.com");
assert_eq!(
host_to_bucket("john.doe.com", ".garage.tld"),
"john.doe.com");
assert_eq!(
host_to_bucket("garage.tld", "garage.tld"),
"garage.tld");
assert_eq!(
host_to_bucket("garage.tld", ".garage.tld"),
"garage.tld");
}
} }