Handle requested path being a directory correctly
This commit is contained in:
parent
6a611c371c
commit
6dd53f96d8
@ -39,6 +39,9 @@ pub enum GetFileError {
|
|||||||
#[error("file not found")]
|
#[error("file not found")]
|
||||||
FileNotFound,
|
FileNotFound,
|
||||||
|
|
||||||
|
#[error("path is directory")]
|
||||||
|
PathIsDirectory,
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Unexpected(#[from] unexpected::Error),
|
Unexpected(#[from] unexpected::Error),
|
||||||
}
|
}
|
||||||
|
@ -330,10 +330,20 @@ impl super::Store for FSStore {
|
|||||||
.object()
|
.object()
|
||||||
.or_unexpected()?;
|
.or_unexpected()?;
|
||||||
|
|
||||||
// TODO this is very not ideal, the whole file is first read totally into memory, and then
|
use gix::object::Kind;
|
||||||
// that is cloned.
|
match file_object.kind {
|
||||||
let data = bytes::Bytes::copy_from_slice(file_object.data.as_slice());
|
Kind::Tree => Err(origin::GetFileError::PathIsDirectory),
|
||||||
Ok(Box::pin(stream::once(async move { Ok(data) })))
|
Kind::Blob => {
|
||||||
|
// TODO this is very not ideal, the whole file is first read totally into memory, and then
|
||||||
|
// that is cloned.
|
||||||
|
let data = bytes::Bytes::copy_from_slice(file_object.data.as_slice());
|
||||||
|
Ok(Box::pin(stream::once(async move { Ok(data) })))
|
||||||
|
}
|
||||||
|
Kind::Commit | Kind::Tag => Err(unexpected::Error::from(
|
||||||
|
format!("found object of kind {} in tree", file_object.kind).as_str(),
|
||||||
|
)
|
||||||
|
.into()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,6 +113,13 @@ impl Service {
|
|||||||
)
|
)
|
||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
|
Err(GetFileError::PathIsDirectory) => {
|
||||||
|
// redirect so that the path has '/' appended to it, which will cause the server to
|
||||||
|
// check index.gmi within the path on the new page load.
|
||||||
|
let mut path = path.into_owned();
|
||||||
|
path.push_str("/");
|
||||||
|
return Ok(self.respond_conn(w, "30", path.as_str(), None).await?);
|
||||||
|
}
|
||||||
Err(GetFileError::Unexpected(e)) => return Err(e.into()),
|
Err(GetFileError::Unexpected(e)) => return Err(e.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -153,6 +153,19 @@ impl Service {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_redirect(&self, status_code: u16, target_uri: &str) -> Response<Body> {
|
||||||
|
Response::builder()
|
||||||
|
.status(status_code)
|
||||||
|
.header("Location", target_uri.to_string())
|
||||||
|
.body(Body::empty())
|
||||||
|
.unwrap_or_else(|err| {
|
||||||
|
self.internal_error(
|
||||||
|
format!("failed to render {status_code} redirect to {target_uri}: {err}",)
|
||||||
|
.as_str(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn https_redirect(&self, domain: domain::Name, req: Request<Body>) -> Response<Body> {
|
fn https_redirect(&self, domain: domain::Name, req: Request<Body>) -> Response<Body> {
|
||||||
let https_addr = self.config.http.https_addr.unwrap();
|
let https_addr = self.config.http.https_addr.unwrap();
|
||||||
|
|
||||||
@ -173,13 +186,12 @@ impl Service {
|
|||||||
.try_into()
|
.try_into()
|
||||||
.or_unexpected_while("constructing new URI")?;
|
.or_unexpected_while("constructing new URI")?;
|
||||||
|
|
||||||
Response::builder()
|
Ok(self.render_redirect(
|
||||||
.status(http::status::StatusCode::PERMANENT_REDIRECT)
|
http::status::StatusCode::PERMANENT_REDIRECT.into(),
|
||||||
.header("Location", uri.to_string())
|
uri.to_string().as_str(),
|
||||||
.body(Body::empty())
|
))
|
||||||
.or_unexpected_while("building redirect")
|
|
||||||
})()
|
})()
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err: unexpected::Error| {
|
||||||
self.internal_error(
|
self.internal_error(
|
||||||
format!("failed to redirect from {} to https: {}", req.uri(), err).as_str(),
|
format!("failed to redirect from {} to https: {}", req.uri(), err).as_str(),
|
||||||
)
|
)
|
||||||
@ -216,6 +228,16 @@ impl Service {
|
|||||||
)
|
)
|
||||||
.as_str(),
|
.as_str(),
|
||||||
),
|
),
|
||||||
|
Err(GetFileError::PathIsDirectory) => {
|
||||||
|
// redirect so that the path has '/' appended to it, which will cause the server to
|
||||||
|
// check index.html within the path on the new page load.
|
||||||
|
let mut path = path.into_owned();
|
||||||
|
path.push_str("/");
|
||||||
|
self.render_redirect(
|
||||||
|
http::status::StatusCode::TEMPORARY_REDIRECT.into(),
|
||||||
|
path.as_str(),
|
||||||
|
)
|
||||||
|
}
|
||||||
Err(GetFileError::Unexpected(e)) => {
|
Err(GetFileError::Unexpected(e)) => {
|
||||||
self.internal_error(format!("failed to fetch file {path}: {e}").as_str())
|
self.internal_error(format!("failed to fetch file {path}: {e}").as_str())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user