forked from Deuxfleurs/garage
Rewrite authority to host while staying on stack
This commit is contained in:
parent
27795a390c
commit
1e52ee9f5b
1 changed files with 21 additions and 20 deletions
|
@ -6,7 +6,7 @@ use futures::future::Future;
|
||||||
use hyper::header::HOST;
|
use hyper::header::HOST;
|
||||||
use hyper::server::conn::AddrStream;
|
use hyper::server::conn::AddrStream;
|
||||||
use hyper::service::{make_service_fn, service_fn};
|
use hyper::service::{make_service_fn, service_fn};
|
||||||
use hyper::{Body, Request, Response, Server, Uri};
|
use hyper::{Body, Request, Response, Server};
|
||||||
|
|
||||||
use garage_model::garage::Garage;
|
use garage_model::garage::Garage;
|
||||||
use garage_util::error::Error;
|
use garage_util::error::Error;
|
||||||
|
@ -58,7 +58,7 @@ async fn handler(
|
||||||
let path = req.uri().path().to_string();
|
let path = req.uri().path().to_string();
|
||||||
let key = percent_encoding::percent_decode_str(&path).decode_utf8()?;
|
let key = percent_encoding::percent_decode_str(&path).decode_utf8()?;
|
||||||
|
|
||||||
info!("host: {}, bucket: {}, key: {}", host, bucket, key);
|
info!("Selected bucket: {}, selected key: {}", bucket, key);
|
||||||
|
|
||||||
Ok(Response::new(Body::from("hello world\n")))
|
Ok(Response::new(Body::from("hello world\n")))
|
||||||
}
|
}
|
||||||
|
@ -66,28 +66,29 @@ async fn handler(
|
||||||
/// Extract host from the authority section given by the HTTP host header
|
/// Extract host from the authority section given by the HTTP host header
|
||||||
///
|
///
|
||||||
/// The HTTP host contains both a host and a port.
|
/// The HTTP host contains both a host and a port.
|
||||||
/// Extracting the port is more complex than just finding the colon (:) symbol.
|
/// Extracting the port is more complex than just finding the colon (:) symbol due to IPv6
|
||||||
/// An example of a case where it does not work: [::1]:3902
|
/// we do not use the collect pattern as there is no way in std rust to collect over a stack allocated value
|
||||||
/// Instead, we use the Uri module provided by Hyper that correctl parses this "authority" section
|
/// check here: https://docs.rs/collect_slice/1.2.0/collect_slice/
|
||||||
fn authority_to_host(authority: &str) -> Result<String, Error> {
|
fn authority_to_host(authority: &str) -> Result<&str, Error> {
|
||||||
// Hyper can not directly parse authority section so we build a fake URL
|
let mut iter = authority.chars().enumerate();
|
||||||
// that contains our authority section
|
let split = match iter.next() {
|
||||||
let mut uri_str: String = "fake://".to_owned();
|
Some((_, '[')) => {
|
||||||
uri_str.push_str(authority);
|
let mut niter = iter.skip_while(|(_, c)| c != &']');
|
||||||
|
niter.next().ok_or(Error::BadRequest(format!("Authority {} has an illegal format", authority)))?;
|
||||||
|
niter.next()
|
||||||
|
},
|
||||||
|
Some((_, _)) => iter.skip_while(|(_, c)| c != &':').next(),
|
||||||
|
None => return Err(Error::BadRequest(format!("Authority is empty"))),
|
||||||
|
};
|
||||||
|
|
||||||
match uri_str.parse::<Uri>() {
|
match split {
|
||||||
Ok(uri) => {
|
Some((i, ':')) => Ok(&authority[..i]),
|
||||||
let host = uri.host().ok_or(Error::BadRequest(format!(
|
None => Ok(authority),
|
||||||
"Unable to extract host from authority"
|
Some((_, _)) => Err(Error::BadRequest(format!("Authority {} has an illegal format", authority))),
|
||||||
)))?;
|
|
||||||
Ok(String::from(host))
|
|
||||||
}
|
|
||||||
_ => Err(Error::BadRequest(format!(
|
|
||||||
"Unable to parse authority (host HTTP header)"
|
|
||||||
))),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn host_to_bucket<'a>(host: &'a str, root: &str) -> &'a str {
|
fn host_to_bucket<'a>(host: &'a str, root: &str) -> &'a str {
|
||||||
if root.len() >= host.len() || !host.ends_with(root) {
|
if root.len() >= host.len() || !host.ends_with(root) {
|
||||||
return host;
|
return host;
|
||||||
|
|
Loading…
Reference in a new issue