diff --git a/Cargo.lock b/Cargo.lock index 22fc676..edb36bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -354,6 +354,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b" +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "cookie" version = "0.17.0" @@ -455,6 +461,17 @@ dependencies = [ "typenum", ] +[[package]] +name = "css-minify" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874c6e2d19f8d4a285083b11a3241bfbe01ac3ed85f26e1e6b34888d960552bd" +dependencies = [ + "derive_more", + "indexmap", + "nom", +] + [[package]] name = "cxx" version = "1.0.93" @@ -595,6 +612,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + [[package]] name = "deunicode" version = "0.4.3" @@ -791,6 +821,7 @@ dependencies = [ "id", "infer", "jwt", + "minify-html", "openid", "refresh_tokens", "rocket", @@ -1634,6 +1665,30 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minify-html" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7754d4669873379ea6a8a5b56e406eb83de713af8a791517ef35a0c832b1e7d5" +dependencies = [ + "aho-corasick", + "css-minify", + "lazy_static", + "memchr", + "minify-js", + "rustc-hash", +] + +[[package]] +name = "minify-js" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c300f90ba1138b5c5daf5d9441dc9bdc67b808aac22cf638362a2647bc213be4" +dependencies = [ + "lazy_static", + "parse-js", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -2053,6 +2108,17 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "parse-js" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30534759e6ad87aa144c396544747e1c25b1020bd133356fd758c8facec764e5" +dependencies = [ + "aho-corasick", + "lazy_static", + "memchr", +] + [[package]] name = "parse-zoneinfo" version = "0.3.0" @@ -2661,6 +2727,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.36.11" @@ -2781,6 +2856,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "semver" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" + [[package]] name = "serde" version = "1.0.158" diff --git a/crates/ezidam/Cargo.toml b/crates/ezidam/Cargo.toml index 1507ac0..9292d82 100644 --- a/crates/ezidam/Cargo.toml +++ b/crates/ezidam/Cargo.toml @@ -16,6 +16,7 @@ rocket_cors = "0.6.0-alpha2" email_address = { workspace = true } chrono-tz = "0.8.2" chrono-humanize = "0.2.2" +minify-html = "0.10.8" # local crates database_pool = { path = "../database_pool" } diff --git a/crates/ezidam/src/lib.rs b/crates/ezidam/src/lib.rs index ac7f574..215c032 100644 --- a/crates/ezidam/src/lib.rs +++ b/crates/ezidam/src/lib.rs @@ -10,6 +10,7 @@ mod guards; mod icons; mod id; mod menu; +mod minify; mod oauth; mod page; mod response_timer; @@ -18,6 +19,7 @@ mod shutdown; mod tokens; pub use crate::email::init as email_init; +use crate::minify::Minify; pub fn rocket_setup(rocket_builder: Rocket) -> Rocket { use cache::CacheControl; @@ -46,6 +48,9 @@ pub fn rocket_setup(rocket_builder: Rocket) -> Rocket { // Static assets let rocket_builder = rocket_builder.mount("/", FileServer::from("static")); + // Minify content + let rocket_builder = Minify::rocket(rocket_builder); + // Routes let rocket_builder = routes::routes(rocket_builder); diff --git a/crates/ezidam/src/minify.rs b/crates/ezidam/src/minify.rs new file mode 100644 index 0000000..c3df3be --- /dev/null +++ b/crates/ezidam/src/minify.rs @@ -0,0 +1,49 @@ +use rocket::fairing::{self, Fairing, Kind}; +use rocket::http::ContentType; +use rocket::{Build, Request, Response, Rocket}; + +pub struct Minify {} + +impl Minify { + pub fn rocket(rocket_builder: Rocket) -> Rocket { + if cfg!(debug_assertions) { + rocket_builder + } else { + rocket_builder.attach(Self {}) + } + } +} + +#[rocket::async_trait] +impl Fairing for Minify { + fn info(&self) -> fairing::Info { + fairing::Info { + name: "Minify HTML", + kind: Kind::Response, + } + } + + async fn on_response<'r>(&self, _request: &'r Request<'_>, response: &mut Response<'r>) { + if response.content_type() == Some(ContentType::HTML) { + let body = response.body_mut(); + + if let Ok(original) = body.to_bytes().await { + let cfg = minify_html::Cfg { + // Be HTML spec compliant + do_not_minify_doctype: true, + ensure_spec_compliant_unquoted_attribute_values: true, + keep_spaces_between_attributes: true, + + // The rest + keep_closing_tags: true, + keep_html_and_head_opening_tags: true, + minify_css: true, + minify_js: true, + ..Default::default() + }; + let minified = minify_html::minify(&original, &cfg); + response.set_sized_body(minified.len(), std::io::Cursor::new(minified)); + } + } + } +}