Support website publishing #7
4 changed files with 41 additions and 5 deletions
|
@ -76,7 +76,9 @@ api_bind_addr = "[::1]:3900" # the S3 API port, HTTP without TLS. Add a reverse
|
||||||
s3_region = "garage" # set this to anything. S3 API calls will fail if they are not made against the region set here.
|
s3_region = "garage" # set this to anything. S3 API calls will fail if they are not made against the region set here.
|
||||||
|
|
||||||
[s3_web]
|
[s3_web]
|
||||||
web_bind_addr = "[::1]:3902"
|
bind_addr = "[::1]:3902"
|
||||||
|
root_domain = ".garage.tld"
|
||||||
|
index = "index.html"
|
||||||
```
|
```
|
||||||
|
|
||||||
Build Garage using `cargo build --release`.
|
Build Garage using `cargo build --release`.
|
||||||
|
|
|
@ -19,3 +19,4 @@ s3_region = "garage" # set this to anything. S3 API calls will fail if they a
|
||||||
[s3_web]
|
[s3_web]
|
||||||
bind_addr = "[::1]:3902"
|
bind_addr = "[::1]:3902"
|
||||||
root_domain = ".garage.tld"
|
root_domain = ".garage.tld"
|
||||||
|
index = "index.html"
|
||||||
|
|
|
@ -56,6 +56,7 @@ pub struct ApiConfig {
|
||||||
pub struct WebConfig {
|
pub struct WebConfig {
|
||||||
pub bind_addr: SocketAddr,
|
pub bind_addr: SocketAddr,
|
||||||
pub root_domain: String,
|
pub root_domain: String,
|
||||||
|
pub index: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_max_concurrent_rpc_requests() -> usize {
|
fn default_max_concurrent_rpc_requests() -> usize {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
@ -55,7 +56,10 @@ async fn handler(
|
||||||
|
|
||||||
// Get path
|
// Get path
|
||||||
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 index = &garage.config.s3_web.index;
|
||||||
|
let key = path_to_key(&path, &index)?;
|
||||||
|
|
||||||
|
info!("Selected bucket: \"{}\", selected key: \"{}\"", bucket, key);
|
||||||
|
|
||||||
// Get bucket descriptor
|
// Get bucket descriptor
|
||||||
let object = garage
|
let object = garage
|
||||||
|
@ -64,8 +68,6 @@ async fn handler(
|
||||||
.await?
|
.await?
|
||||||
.ok_or(Error::NotFound)?;
|
.ok_or(Error::NotFound)?;
|
||||||
|
|
||||||
info!("Selected bucket: \"{}\", selected key: \"{}\"", bucket, key);
|
|
||||||
|
|
||||||
Ok(Response::new(Body::from("hello world\n")))
|
Ok(Response::new(Body::from("hello world\n")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,6 +123,27 @@ fn host_to_bucket<'a>(host: &'a str, root: &str) -> &'a str {
|
||||||
&host[..cursor]
|
&host[..cursor]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Path to key
|
||||||
|
///
|
||||||
|
/// Convert the provided path to the internal key
|
||||||
|
/// When a path ends with "/", we append the index name to match traditional web server behavior
|
||||||
|
/// which is also AWS S3 behavior.
|
||||||
|
fn path_to_key<'a>(path: &'a str, index: &str) -> Result<Cow<'a, str>, Error> {
|
||||||
|
let path_utf8 = percent_encoding::percent_decode_str(&path).decode_utf8()?;
|
||||||
|
match path_utf8.chars().last() {
|
||||||
|
None => Err(Error::BadRequest(format!(
|
||||||
|
"Path must have at least a character"
|
||||||
|
))),
|
||||||
|
Some('/') => {
|
||||||
|
let mut key = String::with_capacity(path_utf8.len() + index.len());
|
||||||
|
key.push_str(&path_utf8);
|
||||||
|
key.push_str(index);
|
||||||
|
Ok(key.into())
|
||||||
|
}
|
||||||
|
Some(_) => Ok(path_utf8.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -170,4 +193,13 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(host_to_bucket("garage.tld", ".garage.tld"), "garage.tld");
|
assert_eq!(host_to_bucket("garage.tld", ".garage.tld"), "garage.tld");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn path_to_key_test() -> Result<(), Error> {
|
||||||
|
assert_eq!(path_to_key("/file%20.jpg", "index.html")?, "/file .jpg");
|
||||||
|
assert_eq!(path_to_key("/%20t/", "index.html")?, "/ t/index.html");
|
||||||
|
assert_eq!(path_to_key("/", "index.html")?, "/index.html");
|
||||||
|
assert!(path_to_key("", "index.html").is_err());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue