From 9d17d34642c1eb9bec7e2d5c3abd319cf7100e7e Mon Sep 17 00:00:00 2001 From: Joscha Date: Sun, 10 Mar 2024 14:41:42 +0100 Subject: [PATCH] Rewrite url paths HTML files should only be accessible without their file ending. Index files should only be accessible via a path that ends in `/`, not directly via name, --- showbits-thermal-printer/src/server/static.rs | 54 +++++++++++++++---- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/showbits-thermal-printer/src/server/static.rs b/showbits-thermal-printer/src/server/static.rs index 5233d6d..dc987ea 100644 --- a/showbits-thermal-printer/src/server/static.rs +++ b/showbits-thermal-printer/src/server/static.rs @@ -8,21 +8,57 @@ use rust_embed::RustEmbed; #[folder = "static"] struct StaticFiles; -struct StaticFile(pub String); +struct StaticFile(String); + +fn not_found() -> Response { + (StatusCode::NOT_FOUND, "404 Not Found").into_response() +} + +fn look_up_path(path: &str) -> Option { + let path = path.trim_start_matches('/'); + let file = StaticFiles::get(path)?; + let mime = mime_guess::from_path(path).first_or_octet_stream(); + let response = ([(header::CONTENT_TYPE, mime.as_ref())], file.data).into_response(); + Some(response) +} impl IntoResponse for StaticFile { fn into_response(self) -> Response { - match StaticFiles::get(&self.0) { - None => (StatusCode::NOT_FOUND, "404 Not Found").into_response(), - Some(file) => { - let mime = mime_guess::from_path(self.0).first_or_octet_stream(); - ([(header::CONTENT_TYPE, mime.as_ref())], file.data).into_response() - } + let mut path = self.0; + if path.is_empty() { + path.push('/') + }; + + if path.ends_with(".html") { + // A file `/foo/bar.html` should not be accessible directly, only + // indirectly at `/foo/bar`. + return not_found(); } + + if path.ends_with("/index") { + // A file `/foo/index.html` should not be accessible directly, only + // indirectly at `/foo/`. + return not_found(); + } + + if path.ends_with('/') { + path.push_str("index"); + } + + if let Some(response) = look_up_path(&path) { + return response; + } + + path.push_str(".html"); + + if let Some(response) = look_up_path(&path) { + return response; + } + + not_found() } } pub async fn get_static_file(uri: Uri) -> impl IntoResponse { - let path = uri.path().trim_start_matches('/').to_string(); - StaticFile(path) + StaticFile(uri.path().to_string()) }