From 3d50af09437083fa2420aa8100f98f9c056affb7 Mon Sep 17 00:00:00 2001 From: Ginger Date: Sat, 28 Feb 2026 20:32:46 -0500 Subject: [PATCH] refactor: Split web code into multiple files, improve static resource loading --- Cargo.lock | 76 ++++++++++++++++++ src/web/Cargo.toml | 5 ++ src/web/askama.toml | 2 + src/web/build.rs | 1 + src/web/mod.rs | 77 ++++++------------- src/web/pages/index.rs | 29 +++++++ src/web/pages/mod.rs | 2 + src/web/pages/resources.rs | 9 +++ src/web/pages/resources/logo.svg | 43 +++++++++++ .../index.css => pages/resources/style.css} | 0 src/web/{ => pages}/templates/_layout.html.j2 | 14 ++-- src/web/{ => pages}/templates/error.html.j2 | 0 src/web/{ => pages}/templates/index.html.j2 | 0 src/web/templates/logo.svg | 1 - 14 files changed, 194 insertions(+), 65 deletions(-) create mode 100644 src/web/askama.toml create mode 100644 src/web/build.rs create mode 100644 src/web/pages/index.rs create mode 100644 src/web/pages/mod.rs create mode 100644 src/web/pages/resources.rs create mode 100644 src/web/pages/resources/logo.svg rename src/web/{css/index.css => pages/resources/style.css} (100%) rename src/web/{ => pages}/templates/_layout.html.j2 (61%) rename src/web/{ => pages}/templates/error.html.j2 (100%) rename src/web/{ => pages}/templates/index.html.j2 (100%) delete mode 120000 src/web/templates/logo.svg diff --git a/Cargo.lock b/Cargo.lock index 51116a70..112224ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1170,8 +1170,10 @@ dependencies = [ "conduwuit_build_metadata", "conduwuit_service", "futures", + "memory-serve", "rand 0.10.0", "thiserror 2.0.18", + "tower-http", "tracing", ] @@ -3027,6 +3029,22 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +[[package]] +name = "memory-serve" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81b5bbad2035f57b1e95f66da606832edd935b47d82312e38e1ccffbcfb8a427" +dependencies = [ + "axum", + "brotli", + "flate2", + "mime_guess", + "sha256", + "tracing", + "urlencoding", + "walkdir", +] + [[package]] name = "meowlnir-antispam" version = "0.1.0" @@ -3043,6 +3061,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "minicbor" version = "2.2.1" @@ -4632,6 +4660,15 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "sanitize-filename" version = "0.6.0" @@ -4993,6 +5030,19 @@ dependencies = [ "digest", ] +[[package]] +name = "sha256" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f880fc8562bdeb709793f00eb42a2ad0e672c4f883bbe59122b926eca935c8f6" +dependencies = [ + "async-trait", + "bytes", + "hex", + "sha2", + "tokio", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -5673,6 +5723,7 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -5894,6 +5945,12 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf-8" version = "0.7.6" @@ -5947,6 +6004,16 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -6161,6 +6228,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/src/web/Cargo.toml b/src/web/Cargo.toml index 84de46da..be8c7ec7 100644 --- a/src/web/Cargo.toml +++ b/src/web/Cargo.toml @@ -26,6 +26,11 @@ futures.workspace = true tracing.workspace = true rand.workspace = true thiserror.workspace = true +tower-http.workspace = true +memory-serve = "2.1.0" + +[build-dependencies] +memory-serve = "2.1.0" [lints] workspace = true diff --git a/src/web/askama.toml b/src/web/askama.toml new file mode 100644 index 00000000..56cb707e --- /dev/null +++ b/src/web/askama.toml @@ -0,0 +1,2 @@ +[general] +dirs = ["pages/templates"] diff --git a/src/web/build.rs b/src/web/build.rs new file mode 100644 index 00000000..bd97b8d5 --- /dev/null +++ b/src/web/build.rs @@ -0,0 +1 @@ +fn main() { memory_serve::load_directory("./pages/resources"); } diff --git a/src/web/mod.rs b/src/web/mod.rs index 25da1139..a0b2ae05 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -1,52 +1,15 @@ use askama::Template; use axum::{ Router, - extract::State, - http::{StatusCode, header}, + http::{HeaderValue, StatusCode, header}, response::{Html, IntoResponse, Response}, - routing::get, }; -use conduwuit_build_metadata::{GIT_REMOTE_COMMIT_URL, GIT_REMOTE_WEB_URL, version_tag}; use conduwuit_service::state; +use tower_http::set_header::SetResponseHeaderLayer; -pub fn build() -> Router { - Router::::new() - .route("/", get(index_handler)) - .route("/_continuwuity/logo.svg", get(logo_handler)) -} +mod pages; -async fn index_handler( - State(services): State, -) -> Result { - #[derive(Debug, Template)] - #[template(path = "index.html.j2")] - struct Index<'a> { - nonce: &'a str, - server_name: &'a str, - first_run: bool, - } - let nonce = rand::random::().to_string(); - - let template = Index { - nonce: &nonce, - server_name: services.config.server_name.as_str(), - first_run: services.firstrun.is_first_run(), - }; - Ok(( - [( - header::CONTENT_SECURITY_POLICY, - format!("default-src 'nonce-{nonce}'; img-src 'self';"), - )], - Html(template.render()?), - )) -} - -async fn logo_handler() -> impl IntoResponse { - ( - [(header::CONTENT_TYPE, "image/svg+xml")], - include_str!("templates/logo.svg").to_owned(), - ) -} +type State = state::State; #[derive(Debug, thiserror::Error)] enum WebError { @@ -58,29 +21,33 @@ impl IntoResponse for WebError { fn into_response(self) -> Response { #[derive(Debug, Template)] #[template(path = "error.html.j2")] - struct Error<'a> { - nonce: &'a str, + struct Error { err: WebError, } - let nonce = rand::random::().to_string(); - let status = match &self { | Self::Render(_) => StatusCode::INTERNAL_SERVER_ERROR, }; - let tmpl = Error { nonce: &nonce, err: self }; + + let tmpl = Error { err: self }; + if let Ok(body) = tmpl.render() { - ( - status, - [( - header::CONTENT_SECURITY_POLICY, - format!("default-src 'none' 'nonce-{nonce}';"), - )], - Html(body), - ) - .into_response() + (status, Html(body)).into_response() } else { (status, "Something went wrong").into_response() } } } + +pub fn build() -> Router { + #[allow(clippy::wildcard_imports)] + use pages::*; + + Router::new() + .merge(index::build()) + .merge(resources::build()) + .layer(SetResponseHeaderLayer::if_not_present( + header::CONTENT_SECURITY_POLICY, + HeaderValue::from_static("default-src 'self'"), + )) +} diff --git a/src/web/pages/index.rs b/src/web/pages/index.rs new file mode 100644 index 00000000..467888a6 --- /dev/null +++ b/src/web/pages/index.rs @@ -0,0 +1,29 @@ +use askama::Template; +use axum::{ + Router, + extract::State, + response::{Html, IntoResponse}, + routing::get, +}; +use conduwuit_service::state; + +use crate::WebError; + +pub(crate) fn build() -> Router { Router::new().route("/", get(index_handler)) } + +async fn index_handler( + State(services): State, +) -> Result { + #[derive(Debug, Template)] + #[template(path = "index.html.j2")] + struct Index<'a> { + server_name: &'a str, + first_run: bool, + } + + let template = Index { + server_name: services.config.server_name.as_str(), + first_run: services.firstrun.is_first_run(), + }; + Ok(Html(template.render()?)) +} diff --git a/src/web/pages/mod.rs b/src/web/pages/mod.rs new file mode 100644 index 00000000..3cab2597 --- /dev/null +++ b/src/web/pages/mod.rs @@ -0,0 +1,2 @@ +pub(super) mod index; +pub(super) mod resources; diff --git a/src/web/pages/resources.rs b/src/web/pages/resources.rs new file mode 100644 index 00000000..b984bb57 --- /dev/null +++ b/src/web/pages/resources.rs @@ -0,0 +1,9 @@ +use axum::Router; + +pub(crate) fn build() -> Router { + Router::new().nest( + "/_continuwuity/resources/", + #[allow(unused_qualifications)] + memory_serve::load!().index_file(None).into_router(), + ) +} diff --git a/src/web/pages/resources/logo.svg b/src/web/pages/resources/logo.svg new file mode 100644 index 00000000..aca988a3 --- /dev/null +++ b/src/web/pages/resources/logo.svg @@ -0,0 +1,43 @@ + + + + diff --git a/src/web/css/index.css b/src/web/pages/resources/style.css similarity index 100% rename from src/web/css/index.css rename to src/web/pages/resources/style.css diff --git a/src/web/templates/_layout.html.j2 b/src/web/pages/templates/_layout.html.j2 similarity index 61% rename from src/web/templates/_layout.html.j2 rename to src/web/pages/templates/_layout.html.j2 index fbae50b5..891550a2 100644 --- a/src/web/templates/_layout.html.j2 +++ b/src/web/pages/templates/_layout.html.j2 @@ -6,22 +6,18 @@ {% block title %}Continuwuity{% endblock %} - - + +
{%~ block content %}{% endblock ~%}
{%~ block footer ~%}