Support website publishing #7

Merged
lx merged 61 commits from feature/website into master 2021-01-15 16:49:51 +00:00
Showing only changes of commit 71721f5bcf - Show all commits

View file

@ -72,11 +72,6 @@ async fn handler_inner(garage: Arc<Garage>, req: Request<Body>) -> Result<Respon
let path = percent_encoding::percent_decode_str(&path).decode_utf8()?; let path = percent_encoding::percent_decode_str(&path).decode_utf8()?;
let (bucket, key) = parse_bucket_key(&path)?; let (bucket, key) = parse_bucket_key(&path)?;
if bucket.len() == 0 {
return Err(Error::Forbidden(format!(
"Operations on buckets not allowed"
)));
}
let (api_key, content_sha256) = check_signature(&garage, &req).await?; let (api_key, content_sha256) = check_signature(&garage, &req).await?;
let allowed = match req.method() { let allowed = match req.method() {
@ -250,18 +245,60 @@ async fn handler_inner(garage: Arc<Garage>, req: Request<Body>) -> Result<Respon
} }
} }
/// Extract the bucket name and the key name from an HTTP path
///
/// S3 internally manages only buckets and keys. This function splits
/// an HTTP path to get the corresponding bucket name and key.
fn parse_bucket_key(path: &str) -> Result<(&str, Option<&str>), Error> { fn parse_bucket_key(path: &str) -> Result<(&str, Option<&str>), Error> {
let path = path.trim_start_matches('/'); let path = path.trim_start_matches('/');
match path.find('/') { let (bucket, key) = match path.find('/') {
Some(i) => { Some(i) => {
let key = &path[i + 1..]; let key = &path[i + 1..];
if key.len() > 0 { if key.len() > 0 {
Ok((&path[..i], Some(key))) (&path[..i], Some(key))
} else { } else {
Ok((&path[..i], None)) (&path[..i], None)
} }
} }
None => Ok((path, None)), None => (path, None),
};
if bucket.len() == 0 {
return Err(Error::BadRequest(format!("No bucket specified")));
}
Ok((bucket, key))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_bucket_containing_a_key() -> Result<(), Error> {
let (bucket, key) = parse_bucket_key("/my_bucket/a/super/file.jpg")?;
assert_eq!(bucket, "my_bucket");
assert_eq!(key.expect("key must be set"), "a/super/file.jpg");
Ok(())
}
#[test]
fn parse_bucket_containing_no_key() -> Result<(), Error> {
let (bucket, key) = parse_bucket_key("/my_bucket/")?;
assert_eq!(bucket, "my_bucket");
assert!(key.is_none());
let (bucket, key) = parse_bucket_key("/my_bucket")?;
assert_eq!(bucket, "my_bucket");
assert!(key.is_none());
Ok(())
}
#[test]
fn parse_bucket_containing_no_bucket() {
let parsed = parse_bucket_key("");
assert!(parsed.is_err());
let parsed = parse_bucket_key("/");
assert!(parsed.is_err());
let parsed = parse_bucket_key("////");
assert!(parsed.is_err());
} }
} }