From 391bb6faebeef6108579ac9182929016008ac74d Mon Sep 17 00:00:00 2001 From: Valentin Brandl Date: Sun, 21 Aug 2022 13:47:07 +0200 Subject: [PATCH 1/2] Use ructe static file support to serve static files with hashes and caching --- Cargo.lock | 2 ++ Cargo.toml | 3 ++- build.rs | 5 ++++- src/lib.rs | 31 +++++++++++++++++++++++++------ src/statics.rs | 2 -- templates/base.rs.html | 3 ++- 6 files changed, 35 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6d732c7..b4f3114 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -880,6 +880,7 @@ dependencies = [ "futures", "git2", "lazy_static", + "mime", "number_prefix", "openssl-probe", "reqwest", @@ -1647,6 +1648,7 @@ dependencies = [ "bytecount", "itertools", "md5", + "mime", "nom", ] diff --git a/Cargo.toml b/Cargo.toml index 37622c9..20cd53c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ dotenv = "0.15.0" futures = "0.3.21" git2 = "0.15.0" lazy_static = "1.4.0" +mime = "0.3" number_prefix = "0.4.0" openssl-probe = "0.1.5" reqwest = "0.11.11" @@ -36,7 +37,7 @@ tracing-log = "0.1.3" tracing-subscriber = { version = "0.3.15", features = ["registry", "env-filter"] } [build-dependencies] -ructe = "0.14.0" +ructe = { version = "0.14.0", features = ["mime03"] } vergen = { version = "7.3.1", default-features = false, features = ["git"] } [dev-dependencies] diff --git a/build.rs b/build.rs index 279203a..9435999 100644 --- a/build.rs +++ b/build.rs @@ -8,5 +8,8 @@ fn main() -> Result<(), RucteError> { let mut config = Config::default(); *config.git_mut().sha_kind_mut() = ShaKind::Short; vergen(config).expect("Unable to generate static repo info"); - Ructe::from_env()?.compile_templates("templates") + let mut ructe = Ructe::from_env()?; + let mut statics = ructe.statics()?; + statics.add_files("static")?; + ructe.compile_templates("templates") } diff --git a/src/lib.rs b/src/lib.rs index baa9c7e..4376e97 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,7 +23,7 @@ use crate::{ config::Settings, error::{Error, Result}, service::{Bitbucket, FormService, GitHub, Gitlab, Service, Sourcehut}, - statics::{CLIENT, CSS, FAVICON, VERSION_INFO}, + statics::{CLIENT, VERSION_INFO}, template::RepoInfo, }; use actix_web::{ @@ -46,6 +46,7 @@ use std::{ sync::atomic::Ordering, time::{Duration, SystemTime}, }; +use templates::statics::{self as template_statics, StaticFile}; use tracing::Instrument; include!(concat!(env!("OUT_DIR"), "/templates.rs")); @@ -462,14 +463,32 @@ async fn async_p404(repo_count: web::Data) -> Result p404(repo_count) } -#[get("/tacit-css.min.css")] -async fn css() -> HttpResponse { - HttpResponse::Ok().content_type("text/css").body(CSS) +/// A duration to add to current time for a far expires header. +static FAR: Duration = Duration::from_secs(180 * 24 * 60 * 60); + +#[get("/static/{filename}")] +async fn static_file( + path: web::Path, + repo_count: web::Data, +) -> Result { + StaticFile::get(&path) + .map(|data| { + let far_expires = SystemTime::now() + FAR; + HttpResponse::Ok() + .insert_header(Expires(far_expires.into())) + .content_type(data.mime.clone()) + .body(data.content) + }) + .map(Result::Ok) + .unwrap_or_else(|| p404(repo_count)) } #[get("/favicon.ico")] async fn favicon32() -> HttpResponse { - HttpResponse::Ok().content_type("image/png").body(FAVICON) + let data = &template_statics::favicon32_png; + HttpResponse::Ok() + .content_type(data.mime.clone()) + .body(data.content) } async fn start_server(listener: TcpListener, settings: Settings) -> std::io::Result { @@ -486,7 +505,7 @@ async fn start_server(listener: TcpListener, settings: Settings) -> std::io::Res .wrap(middleware::NormalizePath::new(TrailingSlash::Trim)) .service(index) .service(health_check) - .service(css) + .service(static_file) .service(favicon32) .service(generate) .default_service(web::to(async_p404)); diff --git a/src/statics.rs b/src/statics.rs index 8aa5d3c..134206a 100644 --- a/src/statics.rs +++ b/src/statics.rs @@ -7,8 +7,6 @@ pub(crate) const VERSION_INFO: VersionInfo = VersionInfo { commit: env!("VERGEN_GIT_SHA_SHORT"), version: env!("CARGO_PKG_VERSION"), }; -pub(crate) const CSS: &str = include_str!("../static/tacit-css.min.css"); -pub(crate) const FAVICON: &[u8] = include_bytes!("../static/favicon32.png"); lazy_static! { pub(crate) static ref CLIENT: reqwest::Client = reqwest::Client::new(); diff --git a/templates/base.rs.html b/templates/base.rs.html index ec9a389..da9a3cf 100644 --- a/templates/base.rs.html +++ b/templates/base.rs.html @@ -1,3 +1,4 @@ +@use super::statics::*; @use crate::statics::VersionInfo; @(title: &str, header: &str, content: Content, version_info: VersionInfo, repo_count: usize) @@ -9,7 +10,7 @@ - + @title From 95c54b95c11220391b7cad4f86c0b8b5cb5d5de6 Mon Sep 17 00:00:00 2001 From: Valentin Brandl Date: Tue, 23 Aug 2022 09:45:05 +0200 Subject: [PATCH 2/2] Remove unnecessary testcase --- tests/resources.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/tests/resources.rs b/tests/resources.rs index 9765f3c..1554058 100644 --- a/tests/resources.rs +++ b/tests/resources.rs @@ -14,18 +14,3 @@ async fn favicon() { assert!(response.status().is_success()); } - -#[actix_rt::test] -async fn tacit_css() { - let test_app = util::spawn_app().await; - - let client = awc::Client::default(); - - let response = client - .get(&format!("{}/tacit-css.min.css", test_app.address)) - .send() - .await - .expect("Failed to execute request"); - - assert!(response.status().is_success()); -}