fix: regression: redirect folders not ending with a slash
This commit is contained in:
parent
3bda00a7ae
commit
8137566988
2 changed files with 63 additions and 71 deletions
67
src/main.rs
67
src/main.rs
|
@ -17,8 +17,8 @@ use {
|
|||
Profile,
|
||||
providers::{Env, Format as _, Toml},
|
||||
},
|
||||
http::ContentType,
|
||||
response::{self, Responder, stream::ByteStream},
|
||||
http::{ContentType, uri::Origin},
|
||||
response::{self, Redirect, Responder, stream::ByteStream},
|
||||
serde::Serialize,
|
||||
},
|
||||
rocket_dyn_templates::{Template, context},
|
||||
|
@ -28,6 +28,7 @@ use {
|
|||
|
||||
enum FileView {
|
||||
Folder(Template),
|
||||
Redirect(Redirect),
|
||||
File(ByteStream<BoxStream<'static, Bytes>>),
|
||||
}
|
||||
|
||||
|
@ -38,6 +39,7 @@ impl<'r> Responder<'r, 'r> for FileView {
|
|||
r.set_header(ContentType::HTML);
|
||||
r
|
||||
}),
|
||||
Self::Redirect(redirect) => redirect.respond_to(req),
|
||||
Self::File(stream) => stream.respond_to(req),
|
||||
}
|
||||
}
|
||||
|
@ -75,12 +77,16 @@ impl From<object_store::Error> for Error {
|
|||
}
|
||||
|
||||
#[rocket::get("/")]
|
||||
async fn index_root(state: &State<Settings>) -> Result<FileView, Error> {
|
||||
index(None, state).await
|
||||
async fn index_root(uri: &Origin<'_>, state: &State<Settings>) -> Result<FileView, Error> {
|
||||
index(None, uri, state).await
|
||||
}
|
||||
|
||||
#[rocket::get("/<path..>")]
|
||||
async fn index(path: Option<PathBuf>, state: &State<Settings>) -> Result<FileView, Error> {
|
||||
async fn index(
|
||||
path: Option<PathBuf>,
|
||||
uri: &Origin<'_>,
|
||||
state: &State<Settings>,
|
||||
) -> Result<FileView, Error> {
|
||||
let object_path = if let Some(url_path) = path.as_ref() {
|
||||
let s = url_path.to_str().ok_or(Error::InvalidRequest(
|
||||
"Path cannot be converted to UTF-8".into(),
|
||||
|
@ -91,31 +97,42 @@ async fn index(path: Option<PathBuf>, state: &State<Settings>) -> Result<FileVie
|
|||
None
|
||||
};
|
||||
|
||||
/*
|
||||
We try first to retrieve list an object as a file. If we fail,
|
||||
we fallback to retrieving the equivalent folder.
|
||||
*/
|
||||
|
||||
// We try first to retrieve list an object as a file.
|
||||
if let Some(object_path) = &object_path
|
||||
&& object_exists(object_path, &state).await?
|
||||
{
|
||||
log::info!("serving S3 object at {}", &object_path);
|
||||
serve_object(&object_path, &state).await
|
||||
} else {
|
||||
let path = path.unwrap_or_default();
|
||||
log::info!("listing S3 objects at {}", path.display());
|
||||
let objects = file_view(object_path, &state).await?;
|
||||
|
||||
let rendered = Template::render(
|
||||
"index",
|
||||
context! {
|
||||
path: format!("{}/", path.display()),
|
||||
objects
|
||||
},
|
||||
);
|
||||
|
||||
Ok(FileView::Folder(rendered))
|
||||
return serve_object(&object_path, &state).await;
|
||||
}
|
||||
|
||||
// If we fail, we fallback to retrieving the equivalent folder.
|
||||
// For hyperlinks in the generated HTML to work properly, let's
|
||||
// normalize the path to end with a slash.
|
||||
if !uri.path().ends_with("/") {
|
||||
// If the path does not end with a slash, we redirect to
|
||||
// the normalized path with a slash appended.
|
||||
let redirect = uri
|
||||
.map_path(|p| format!("{}/", p))
|
||||
.expect("cannot append slash to origin URL, this should never happen!");
|
||||
return Ok(FileView::Redirect(Redirect::permanent(
|
||||
redirect.to_string(),
|
||||
)));
|
||||
}
|
||||
|
||||
// We can now assume we have a full path to a folder,
|
||||
// ending with a slash.
|
||||
let path = path.unwrap_or_default();
|
||||
log::info!("listing S3 objects at {}", path.display());
|
||||
let objects = file_view(object_path, &state).await?;
|
||||
let rendered = Template::render(
|
||||
"index",
|
||||
context! {
|
||||
path: format!("{}/", path.display()),
|
||||
objects
|
||||
},
|
||||
);
|
||||
|
||||
Ok(FileView::Folder(rendered))
|
||||
}
|
||||
|
||||
async fn object_exists(s3_path: &ObjectStorePath, settings: &Settings) -> Result<bool, Error> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue