diff --git a/Cargo.lock b/Cargo.lock index 5cc7e58..b939b19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,6 +61,50 @@ dependencies = [ "memchr", ] +[[package]] +name = "askama" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28" +dependencies = [ + "askama_derive", + "askama_escape", + "humansize", + "num-traits", + "percent-encoding", +] + +[[package]] +name = "askama_derive" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19fe8d6cb13c4714962c072ea496f3392015f0989b1a2847bb4b2d9effd71d83" +dependencies = [ + "askama_parser", + "basic-toml", + "mime", + "mime_guess", + "proc-macro2", + "quote", + "serde", + "syn", +] + +[[package]] +name = "askama_escape" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" + +[[package]] +name = "askama_parser" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0" +dependencies = [ + "nom", +] + [[package]] name = "async-trait" version = "0.1.83" @@ -111,6 +155,15 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "basic-toml" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8" +dependencies = [ + "serde", +] + [[package]] name = "bitflags" version = "2.6.0" @@ -254,6 +307,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -282,6 +336,7 @@ dependencies = [ name = "dynamic-preauth" version = "0.1.0" dependencies = [ + "askama", "salvo", "tokio", "tracing", @@ -528,6 +583,12 @@ dependencies = [ "http", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hmac" version = "0.12.1" @@ -583,6 +644,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humansize" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" +dependencies = [ + "libm", +] + [[package]] name = "hyper" version = "1.5.2" @@ -865,6 +935,12 @@ version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -915,6 +991,22 @@ dependencies = [ "unicase", ] +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.2" @@ -990,6 +1082,16 @@ dependencies = [ "libc", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1128,6 +1230,12 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "path-slash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" + [[package]] name = "pem" version = "3.0.4" @@ -1364,6 +1472,40 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rust-embed" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa66af4a4fdd5e7ebc276f115e895611a34739a9c1c01028383d612d550953c0" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6125dbc8867951125eec87294137f4e9c2c96566e61bf72c45095a7c77761478" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e5347777e9aacb56039b0e1f28785929a8a3b709e87482e7442c72e7c12529d" +dependencies = [ + "sha2", + "walkdir", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -1450,6 +1592,7 @@ checksum = "bf71b51a4d651ddf3d660db7ae483baab3f1bd81f1f82f177731bf43f6052c34" dependencies = [ "salvo-jwt-auth", "salvo-proxy", + "salvo-serve-static", "salvo_core", "salvo_extra", ] @@ -1503,6 +1646,26 @@ dependencies = [ "syn", ] +[[package]] +name = "salvo-serve-static" +version = "0.74.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177629247d64bd659f68e5a698162c0890350e52867a5d3eefee61242738d818" +dependencies = [ + "hex", + "mime", + "mime-infer", + "path-slash", + "percent-encoding", + "rust-embed", + "salvo_core", + "serde", + "serde_json", + "time", + "tokio", + "tracing", +] + [[package]] name = "salvo_core" version = "0.74.3" @@ -1584,6 +1747,15 @@ dependencies = [ "syn", ] +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.27" @@ -2238,6 +2410,16 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -2369,6 +2551,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index e0fd87c..4d21673 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -salvo = { version = "0.74.3", features = ["affix-state", "logging"] } +askama = "0.12.1" +salvo = { version = "0.74.3", features = ["affix-state", "logging", "serve-static"] } tokio = { version = "1", features = ["macros"] } tracing = "0.1" tracing-subscriber = "0.3" diff --git a/src/main.rs b/src/main.rs index 08a89f0..d244d41 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use std::path; +use askama::Template; use salvo::http::HeaderValue; use salvo::logging::Logger; @@ -47,16 +48,29 @@ fn search(buf: &[u8], pattern: &[u8], start_index: usize) -> Option { None } -#[handler] -async fn hello() -> &'static str { - "Hello World" +#[derive(Template)] +#[template(path = "index.html")] +struct IndexTemplate<'a> { + available: Vec<&'a str>, } #[handler] -async fn download(depot: &mut Depot, _req: &mut Request, res: &mut Response) { +async fn index(res: &mut Response, depot: &Depot) { let state = depot.obtain::().unwrap(); - let data = state.exe_with_key("windows", b"test"); // Clone the data - let name = &state.executables.get("windows").unwrap().name; + + let index_tmpl = IndexTemplate { + available: state.executables.keys().map(|x| *x).collect(), + }; + res.render(Text::Html(index_tmpl.render().unwrap())); +} + +#[handler] +async fn download(depot: &mut Depot, req: &mut Request, res: &mut Response) { + let article_id = req.param::("id").unwrap(); + + let state = depot.obtain::().unwrap(); + let executable = state.executables.get(&article_id as &str).unwrap(); + let data = executable.with_key(b"test"); if let Err(e) = res.write_body(data) { eprintln!("Error writing body: {}", e); @@ -64,7 +78,8 @@ async fn download(depot: &mut Depot, _req: &mut Request, res: &mut Response) { res.headers.insert( "Content-Disposition", - HeaderValue::from_str(format!("attachment; filename=\"{}\"", name).as_str()).unwrap(), + HeaderValue::from_str(format!("attachment; filename=\"{}\"", executable.filename).as_str()) + .unwrap(), ); res.headers.insert( "Content-Type", @@ -79,7 +94,7 @@ struct State<'a> { #[derive(Default, Clone, Debug)] struct Executable { data: Vec, - name: String, + filename: String, key_start: usize, key_end: usize, } @@ -100,26 +115,27 @@ impl<'a> State<'a> { let exe = Executable { data, - name: filename, + filename, key_start: key_start, key_end: key_end, }; self.executables.insert(exe_type, exe); } - fn exe_with_key(&self, executable_type: &str, new_key: &[u8]) -> Vec { - let exe = self.executables.get(executable_type).unwrap(); +} - let mut data = exe.data.clone(); +impl Executable { + fn with_key(&self, new_key: &[u8]) -> Vec { + let mut data = self.data.clone(); // Copy the key into the data for i in 0..new_key.len() { - data[exe.key_start + i] = new_key[i]; + data[self.key_start + i] = new_key[i]; } // If the new key is shorter than the old key, we just write over the remaining data - if new_key.len() < exe.key_end - exe.key_start { - for i in exe.key_start + new_key.len()..exe.key_end { + if new_key.len() < self.key_end - self.key_start { + for i in self.key_start + new_key.len()..self.key_end { data[i] = b' '; } } @@ -143,8 +159,9 @@ async fn main() { let router = Router::new() .hoop(affix_state::inject(state)) - .get(hello) - .push(Router::with_path("download").get(download)); + .push(Router::with_path("download/").get(download)) + .push(Router::new().get(index)) + .push(Router::with_path("<**path>").get(StaticDir::new(["./public"]))); let service = Service::new(router).hoop(Logger::new()); diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..5454175 --- /dev/null +++ b/templates/index.html @@ -0,0 +1 @@ +Available for download: {{ available|join(", ") }}