Skip to main content

fn0_deploy/
static_files.rs

1use anyhow::{Result, anyhow};
2use std::path::{Path, PathBuf};
3
4pub struct StaticFile {
5    pub relative_path: String,
6    pub absolute_path: PathBuf,
7    pub size: u64,
8    pub content_type: &'static str,
9}
10
11pub fn collect_static_files(dir: &Path) -> Result<Vec<StaticFile>> {
12    let mut out = Vec::new();
13    if !dir.exists() {
14        return Ok(out);
15    }
16    walk_collect(dir, dir, &mut out)?;
17    Ok(out)
18}
19
20fn walk_collect(base: &Path, dir: &Path, out: &mut Vec<StaticFile>) -> Result<()> {
21    for entry in std::fs::read_dir(dir)? {
22        let entry = entry?;
23        let path = entry.path();
24        if path.is_dir() {
25            if path.file_name().and_then(|s| s.to_str()) == Some("ssr")
26                && path.parent() == Some(base)
27            {
28                continue;
29            }
30            walk_collect(base, &path, out)?;
31            continue;
32        }
33        let metadata = entry.metadata()?;
34        let rel = path
35            .strip_prefix(base)
36            .map_err(|e| anyhow!("strip_prefix: {e}"))?
37            .to_string_lossy()
38            .replace('\\', "/");
39        out.push(StaticFile {
40            relative_path: rel,
41            absolute_path: path.clone(),
42            size: metadata.len(),
43            content_type: content_type_for(&path),
44        });
45    }
46    Ok(())
47}
48
49pub fn content_type_for(path: &Path) -> &'static str {
50    match path.extension().and_then(|e| e.to_str()) {
51        Some("html") => "text/html; charset=utf-8",
52        Some("css") => "text/css; charset=utf-8",
53        Some("js") | Some("mjs") | Some("cjs") => "application/javascript; charset=utf-8",
54        Some("json") => "application/json; charset=utf-8",
55        Some("map") => "application/json; charset=utf-8",
56        Some("png") => "image/png",
57        Some("jpg") | Some("jpeg") => "image/jpeg",
58        Some("gif") => "image/gif",
59        Some("svg") => "image/svg+xml",
60        Some("ico") => "image/x-icon",
61        Some("webp") => "image/webp",
62        Some("woff") => "font/woff",
63        Some("woff2") => "font/woff2",
64        Some("ttf") => "font/ttf",
65        Some("otf") => "font/otf",
66        Some("eot") => "application/vnd.ms-fontobject",
67        Some("txt") => "text/plain; charset=utf-8",
68        Some("xml") => "application/xml; charset=utf-8",
69        Some("pdf") => "application/pdf",
70        Some("mp4") => "video/mp4",
71        Some("webm") => "video/webm",
72        Some("mp3") => "audio/mpeg",
73        Some("wav") => "audio/wav",
74        _ => "application/octet-stream",
75    }
76}