about summary refs log tree commit diff
path: root/kittybox-rs/templates
diff options
context:
space:
mode:
Diffstat (limited to 'kittybox-rs/templates')
-rw-r--r--kittybox-rs/templates/Cargo.toml4
-rw-r--r--kittybox-rs/templates/build.rs88
-rw-r--r--kittybox-rs/templates/src/lib.rs21
3 files changed, 95 insertions, 18 deletions
diff --git a/kittybox-rs/templates/Cargo.toml b/kittybox-rs/templates/Cargo.toml
index ffdfc25..7090046 100644
--- a/kittybox-rs/templates/Cargo.toml
+++ b/kittybox-rs/templates/Cargo.toml
@@ -5,6 +5,10 @@ edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
+[build-dependencies]
+libflate = "^1.2.0"
+walkdir = "^2.3.2"
+
 [dev-dependencies]
 faker_rand = "^0.1.1"
 rand = "^0.8.5"
diff --git a/kittybox-rs/templates/build.rs b/kittybox-rs/templates/build.rs
index 1140060..ccd5b19 100644
--- a/kittybox-rs/templates/build.rs
+++ b/kittybox-rs/templates/build.rs
@@ -1,26 +1,90 @@
-fn main() {
+use std::ffi::OsStr;
+
+use libflate::gzip::Encoder;
+use walkdir::WalkDir;
+
+fn main() -> Result<(), std::io::Error> {
     use std::env;
     let out_dir = std::path::PathBuf::from(env::var("OUT_DIR").unwrap());
-    println!("cargo:rerun-if-changed=assets/");
-    let assets = std::fs::read_dir("assets").unwrap();
-    for file in assets.map(|a| a.unwrap()) {
-        std::fs::copy(
-            file.path(),
-            out_dir.join(file.file_name())
-        )
-            .unwrap();
-    }
+
     println!("cargo::rerun-if-changed=javascript/");
     if let Ok(exit) = std::process::Command::new("tsc")
         .arg("--outDir")
         .arg(&out_dir)
         .current_dir("javascript")
-        .spawn()
-        .unwrap()
+        .spawn()?
         .wait()
     {
         if !exit.success() {
             std::process::exit(exit.code().unwrap_or(1))
         }
     }
+
+    println!("cargo:rerun-if-changed=assets/");
+    let assets_path = std::path::Path::new("assets");
+    let mut assets = WalkDir::new(&assets_path)
+        .into_iter();
+    while let Some(Ok(entry)) = assets.next() {
+        if entry.file_type().is_dir() {
+            if let Err(err) = std::fs::create_dir(&out_dir.join(entry.path())) {
+                if err.kind() != std::io::ErrorKind::AlreadyExists {
+                    return Err(err)
+                }
+            }
+        } else {
+            std::fs::copy(entry.path(), &out_dir.join(entry.path().strip_prefix(assets_path).unwrap()))?;
+        }
+    }
+
+    let walker = WalkDir::new(&out_dir)
+        .into_iter()
+        .map(Result::unwrap)
+        .filter(|e| {
+            e.file_type().is_file() && e.path().extension().unwrap() != "gz"
+        });
+    for entry in walker {
+        let normal_path = entry.path();
+        let gzip_path = normal_path.with_extension({
+            let mut extension = normal_path
+                .extension()
+                .unwrap()
+                .to_owned();
+            extension.push(OsStr::new(".gz"));
+            extension
+        });
+        eprintln!(
+            "{} -> {}",
+            normal_path.strip_prefix(&out_dir).unwrap().display(),
+            gzip_path.strip_prefix(&out_dir).unwrap().display()
+        );
+        {
+            let mut out_file = std::fs::OpenOptions::new()
+                .create(true)
+                .truncate(true)
+                .write(true)
+                .open(&gzip_path)?;
+
+            let mut in_file = std::fs::File::open(&normal_path)?;
+
+            let mut encoder = Encoder::new(&mut out_file)?;
+            std::io::copy(&mut in_file, &mut encoder)?;
+            encoder.finish().into_result()?;
+        }
+
+        let normal_len: f64 = std::fs::metadata(&normal_path).unwrap().len() as f64;
+        let gzipped_len: f64 = std::fs::metadata(&gzip_path).unwrap().len() as f64;
+        let ratio = gzipped_len / normal_len;
+        eprintln!("Ratio: {}", ratio);
+        if ratio <= 0.9 {
+            std::fs::remove_file(&normal_path)?
+        } else {
+            println!(
+                "cargo:warning={} compression ratio is {} (> 0.9), leaving as is",
+                entry.path().display(),
+                ratio
+            );
+            std::fs::remove_file(&gzip_path)?
+        }
+    }
+    Ok(())
 }
diff --git a/kittybox-rs/templates/src/lib.rs b/kittybox-rs/templates/src/lib.rs
index 5b3a8df..8d5d5fa 100644
--- a/kittybox-rs/templates/src/lib.rs
+++ b/kittybox-rs/templates/src/lib.rs
@@ -13,13 +13,15 @@ pub mod assets {
     use axum::response::{IntoResponse, Response};
     use axum::extract::Path;
     use axum::http::StatusCode;
-    use axum::http::header::{CONTENT_TYPE, CACHE_CONTROL};
+    use axum::http::header::{CONTENT_TYPE, CONTENT_ENCODING, CACHE_CONTROL};
 
-    const ASSETS: include_dir::Dir<'static> = include_dir::include_dir!("$OUT_DIR");
+    const ASSETS: include_dir::Dir<'static> = include_dir::include_dir!("$OUT_DIR/");
     const CACHE_FOR_A_DAY: &str = "max-age=86400";
+    const GZIP: &str = "gzip";
 
-    pub async fn statics(Path(path): Path<String>) -> Response {
-
+    pub async fn statics(
+        Path(path): Path<String>
+    ) -> Response {
         let content_type: &'static str = if path.ends_with(".js") {
             "application/javascript"
         } else if path.ends_with(".css") {
@@ -30,12 +32,19 @@ pub mod assets {
             "application/octet-stream"
         };
 
-        match ASSETS.get_file(path) {
+        match ASSETS.get_file(path.clone() + ".gz") {
             Some(file) => (StatusCode::OK,
                            [(CONTENT_TYPE, content_type),
+                            (CONTENT_ENCODING, GZIP),
                             (CACHE_CONTROL, CACHE_FOR_A_DAY)],
                            file.contents()).into_response(),
-            None => StatusCode::NOT_FOUND.into_response()
+            None => match ASSETS.get_file(path) {
+                Some(file) => (StatusCode::OK,
+                               [(CONTENT_TYPE, content_type),
+                                (CACHE_CONTROL, CACHE_FOR_A_DAY)],
+                               file.contents()).into_response(),
+                None => StatusCode::NOT_FOUND.into_response()
+            }
         }
     }
 }