index : static-web-server.git

ascending towards madness

author Jose Quintana <joseluisquintana20@gmail.com> 2021-01-11 23:54:09.0 +00:00:00
committer Jose Quintana <joseluisquintana20@gmail.com> 2021-01-11 23:54:09.0 +00:00:00
commit
7b829531a0b4ff72e482cd89710c0a6278bdff84 [patch]
tree
31fe055b931c581cfb2c160320d05b38f1212034
parent
a502b3401de91e52d924a8dde2bc0f17c6b28c6f
download
7b829531a0b4ff72e482cd89710c0a6278bdff84.tar.gz

feat: cache control headers for assets



Diff

 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(-)

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<warp::fs::File> {
    // 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;