From 7b829531a0b4ff72e482cd89710c0a6278bdff84 Mon Sep 17 00:00:00 2001 From: Jose Quintana Date: Tue, 12 Jan 2021 00:54:09 +0100 Subject: [PATCH] feat: cache control headers for assets --- Cargo.lock | 28 ++++++++++++++-------------- src/bin/server.rs | 5 +++++ src/core/cache.rs | 41 +++++++++++++++++++++++++++++++++++++++++ src/core/mod.rs | 1 + 4 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 src/core/cache.rs diff --git a/Cargo.lock b/Cargo.lock index 435178c..5493d35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,9 +41,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee67c11feeac938fae061b232e38e0b6d94f97a9df10e6271319325ac4c56a86" +checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" [[package]] name = "async-compression" @@ -56,7 +56,7 @@ dependencies = [ "flate2", "futures-core", "memchr", - "pin-project-lite 0.2.3", + "pin-project-lite 0.2.4", ] [[package]] @@ -169,9 +169,9 @@ checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" [[package]] name = "bytes" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1f8e949d755f9d79112b5bb46938e0ef9d3804a0b16dfab13aafcaa5f0fa72" +checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" [[package]] name = "cc" @@ -374,7 +374,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-task", - "pin-project-lite 0.2.3", + "pin-project-lite 0.2.4", "pin-utils", "slab", ] @@ -484,7 +484,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747" dependencies = [ - "bytes 1.0.0", + "bytes 1.0.1", "fnv", "itoa", ] @@ -625,9 +625,9 @@ checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" [[package]] name = "log" -version = "0.4.11" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2" dependencies = [ "cfg-if 0.1.10", ] @@ -886,9 +886,9 @@ checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" [[package]] name = "pin-project-lite" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba36e0a6cc5a4c645073f4984f1ed55d09f5857d4de7c14550baa81a39ef5a17" +checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827" [[package]] name = "pin-utils" @@ -1051,9 +1051,9 @@ checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" [[package]] name = "serde" -version = "1.0.118" +version = "1.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" +checksum = "9bdd36f49e35b61d49efd8aa7fc068fd295961fd2286d0b2ee9a4c7a14e99cc3" [[package]] name = "serde_json" @@ -1344,7 +1344,7 @@ checksum = "9f47026cdc4080c07e49b37087de021820269d996f581aac150ef9e5583eefe3" dependencies = [ "cfg-if 1.0.0", "log", - "pin-project-lite 0.2.3", + "pin-project-lite 0.2.4", "tracing-attributes", "tracing-core", ] diff --git a/src/bin/server.rs b/src/bin/server.rs index b9e4dec..994c579 100644 --- a/src/bin/server.rs +++ b/src/bin/server.rs @@ -18,12 +18,14 @@ async fn server(opts: config::Options) -> Result { let public_head = warp::head().and( warp::fs::dir(opts.root.clone()) + .map(cache::control_headers) .with(warp::trace::request()) .recover(rejection::handle_rejection), ); let public_get_default = warp::get().and( warp::fs::dir(opts.root.clone()) + .map(cache::control_headers) .with(warp::trace::request()) .recover(rejection::handle_rejection), ); @@ -40,6 +42,7 @@ async fn server(opts: config::Options) -> Result { .and(accept_encoding("br")) .and( warp::fs::dir(opts.root.clone()) + .map(cache::control_headers) .with(warp::trace::request()) .with(warp::compression::brotli(true)) .recover(rejection::handle_rejection), @@ -54,6 +57,7 @@ async fn server(opts: config::Options) -> Result { .and(accept_encoding("deflate")) .and( warp::fs::dir(opts.root.clone()) + .map(cache::control_headers) .with(warp::trace::request()) .with(warp::compression::deflate(true)) .recover(rejection::handle_rejection), @@ -68,6 +72,7 @@ async fn server(opts: config::Options) -> Result { .and(accept_encoding("gzip")) .and( warp::fs::dir(opts.root.clone()) + .map(cache::control_headers) .with(warp::trace::request()) .with(warp::compression::gzip(true)) .recover(rejection::handle_rejection), diff --git a/src/core/cache.rs b/src/core/cache.rs new file mode 100644 index 0000000..267ca7f --- /dev/null +++ b/src/core/cache.rs @@ -0,0 +1,41 @@ +const CACHE_EXT_ONE_HOUR: [&'static str; 4] = ["atom", "json", "rss", "xml"]; +const CACHE_EXT_ONE_YEAR: [&'static str; 30] = [ + "bmp", "bz2", "css", "map", "doc", "gif", "gz", "htc", "ico", "jpg", "mp3", "mp4", "ogg", + "ogv", "pdf", "png", "rar", "tar", "tgz", "wav", "weba", "webm", "webp", "woff", "zip", "jpeg", + "js", "mjs", "rtf", "woff2", +]; + +/// It applies the corresponding Cache-Control headers based on a set of file types. +pub fn control_headers(res: warp::fs::File) -> warp::reply::WithHeader { + // Default max-age value in seconds (one day) + let mut max_age = 60 * 60 * 24 as u64; + + if let Some(ext) = res.path().extension() { + if let Some(ext) = ext.to_str() { + // Caching (one year) + if CACHE_EXT_ONE_YEAR.iter().any(|n| *n == ext) { + max_age = 60 * 60 * 24 * 365; + } + // Caching (one hour) + if CACHE_EXT_ONE_HOUR.iter().any(|n| *n == ext) { + max_age = 60 * 60; + } + } + } + + // HTML file types and others + warp::reply::with_header( + res, + "cache-control", + [ + "public, max-age=".to_string(), + duration(max_age).to_string(), + ] + .concat(), + ) +} + +/// It caps a duration value at ~136 years. +fn duration(n: u64) -> u32 { + std::cmp::min(n.clone(), u32::MAX as u64) as u32 +} diff --git a/src/core/mod.rs b/src/core/mod.rs index 161938e..188dde3 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -1,3 +1,4 @@ +pub mod cache; pub mod config; pub mod helpers; pub mod logger; -- libgit2 1.7.2