diff --git a/crates/treehouse/src/cli/serve.rs b/crates/treehouse/src/cli/serve.rs index 4f2f0db..38279a5 100644 --- a/crates/treehouse/src/cli/serve.rs +++ b/crates/treehouse/src/cli/serve.rs @@ -2,7 +2,6 @@ mod live_reload; mod picture_upload; -use std::fmt::Write; use std::{net::Ipv4Addr, sync::Arc}; use axum::http::header::LOCATION; @@ -22,9 +21,9 @@ use tracing::{error, info, instrument}; use crate::dirs::Dirs; use crate::sources::Sources; +use crate::state::Source; use crate::vfs::asynch::AsyncDir; use crate::vfs::{self, VPath}; -use crate::{html::EscapeHtml, state::Source}; mod system { use crate::vfs::VPath; @@ -76,6 +75,12 @@ struct VfsQuery { #[instrument(skip(state))] async fn get_static_file(path: &str, query: &VfsQuery, state: &Server) -> Option<Response> { let vpath = VPath::try_new(path).ok()?; + + if let Some(target) = state.sources.config.redirects.path.get(vpath) { + let url = vfs::url(&state.sources.config.site, state.target.sync(), target)?; + return Some((StatusCode::MOVED_PERMANENTLY, [(LOCATION, url)]).into_response()); + } + let content = state.target.content(vpath).await?; let content_type = HeaderValue::from_str(content.kind()).inspect_err( |err| error!(?err, content_type = ?content.kind(), "content type cannot be used as an HTTP header"), diff --git a/crates/treehouse/src/config.rs b/crates/treehouse/src/config.rs index 5570f17..67d7493 100644 --- a/crates/treehouse/src/config.rs +++ b/crates/treehouse/src/config.rs @@ -88,9 +88,9 @@ pub struct Feed { #[derive(Debug, Clone, Deserialize, Serialize)] pub struct Redirects { - /// Page redirects. When a user navigates to a page, if they navigate to `url`, they will - /// be redirected to `page[url]`. - pub page: HashMap<String, String>, + /// Path redirects. When a user requests a path, if they request `p`, they will be redirected + /// to `path[p]` with a `301 Moved Permanently` status code. + pub path: HashMap<VPathBuf, VPathBuf>, } #[derive(Debug, Clone, Deserialize, Serialize)]