diff --git a/Cargo.lock b/Cargo.lock index a0dda42..a153332 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -66,6 +66,50 @@ dependencies = [ "windows-sys 0.59.0", ] +[[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 = "autocfg" version = "1.4.0" @@ -197,6 +241,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" @@ -435,6 +488,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" @@ -652,6 +714,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 = "litemap" version = "0.7.4" @@ -692,6 +760,22 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[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" @@ -712,6 +796,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[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" @@ -722,6 +816,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "object" version = "0.36.7" @@ -992,14 +1095,17 @@ dependencies = [ name = "server" version = "0.1.0" dependencies = [ + "askama", "axum", "axum-extra", "backoff", "clap", + "lazy_static", "tokio", "tracing", "tracing-subscriber", "ureq", + "uuid", ] [[package]] @@ -1230,6 +1336,12 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + [[package]] name = "unicode-ident" version = "1.0.14" @@ -1287,6 +1399,15 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +dependencies = [ + "getrandom", +] + [[package]] name = "valuable" version = "0.1.0" diff --git a/flake.nix b/flake.nix index faa179f..f8633c7 100644 --- a/flake.nix +++ b/flake.nix @@ -86,6 +86,45 @@ }; packages = { + run-stack = pkgs.writeShellApplication { + name = "run-stack"; + runtimeInputs = [ + pkgs.tinyproxy + pkgs.simple-http-server + ]; + text = + let + proxyConfig = pkgs.writeTextFile { + name = "proxy.conf"; + text = '' + ReversePath "/" "http://0.0.0.0:8001/" + ReversePath "/api/" "http://0.0.0.0:8002/api/" + ReverseOnly Yes + Port 8000 + ReverseBaseURL "http://0.0.0.0:8000/" + ''; + }; + in + '' + simple-http-server --index --port 8001 frontend & + PID_FRONTEND=$! + cargo run -- --listen-address 0.0.0.0:8002 & + PID_BACKEND=$! + tinyproxy -d -c ${proxyConfig} & + PID_PROXY=$! + + cleanup() { + kill $PID_FRONTEND $PID_BACKEND $PID_PROXY + wait $PID_FRONTEND $PID_BACKEND $PID_PROXY + exit 0 + } + + trap cleanup SIGINT + + wait $PID_FRONTEND $PID_BACKEND $PID_PROXY + ''; + }; + server-deps = craneLib.buildDepsOnly commonAttrs; server-docs = craneLib.cargoDoc ( diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..2917354 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,21 @@ + + + + + + + + Demo + + +
+
+ + + diff --git a/frontend/style.css b/frontend/style.css new file mode 100644 index 0000000..ea8c79d --- /dev/null +++ b/frontend/style.css @@ -0,0 +1,2 @@ +@import "https://unpkg.com/open-props"; +@import "https://unpkg.com/open-props/normalize.min.css"; diff --git a/server/Cargo.toml b/server/Cargo.toml index 25460be..b319235 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -4,12 +4,15 @@ version = "0.1.0" edition = "2021" [dependencies] +askama = "0.12" axum = { version = "0.8", features = ["tracing"] } axum-extra = { version = "0.10", features = ["typed-routing"] } clap = { version = "4", features = ["derive"] } +lazy_static = "1.5.0" tokio = { version = "1", features = [ "full", "tracing"] } tracing = "0.1" tracing-subscriber = "0.3" +uuid = { version = "1", features = ["v4"] } [dev-dependencies] ureq = "2" diff --git a/server/src/item.rs b/server/src/item.rs new file mode 100644 index 0000000..2a90bb4 --- /dev/null +++ b/server/src/item.rs @@ -0,0 +1,15 @@ +use askama::Template; +use uuid::Uuid; + +#[derive(Debug, Clone)] +pub struct Item { + pub id: Uuid, + pub name: String, + pub price: u128, +} + +#[derive(Template)] +#[template(path = "items.html")] +pub struct ItemsTemplate<'a> { + pub items: &'a Vec, +} diff --git a/server/src/lib.rs b/server/src/lib.rs index a623de1..a674a54 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1,4 +1,5 @@ pub mod cli; +pub mod item; pub mod routes; use crate::cli::CliArgs; diff --git a/server/src/routes.rs b/server/src/routes.rs index f1f4890..303ee21 100644 --- a/server/src/routes.rs +++ b/server/src/routes.rs @@ -1,12 +1,27 @@ -use axum::http::StatusCode; +use askama::Template; +use axum::response::Html; use axum_extra::routing::TypedPath; +use lazy_static::lazy_static; +use std::sync::Mutex; use tracing::instrument; +use crate::item::{Item, ItemsTemplate}; + +lazy_static! { + static ref ITEMS: Mutex> = Mutex::new(vec![Item { + id: uuid::Uuid::new_v4(), + name: "test".to_string(), + price: 12345 + }]); +} + #[derive(TypedPath, Debug, Clone, Copy)] #[typed_path("/api/v1/items")] pub struct GetItemsPath; #[instrument(level = "trace", ret)] -pub async fn get_items_handler(_: GetItemsPath) -> (StatusCode, &'static str) { - (StatusCode::OK, "Hello World!") +pub async fn get_items_handler(_: GetItemsPath) -> Html { + let items = ITEMS.lock().unwrap(); + let template = ItemsTemplate { items: &items }; + Html(template.render().unwrap()) } diff --git a/server/templates/items.html b/server/templates/items.html new file mode 100644 index 0000000..247e35f --- /dev/null +++ b/server/templates/items.html @@ -0,0 +1,12 @@ + + + + + + {% for item in items %} + + + + + {% endfor %} +
IdName
{{ item.id }}{{ item.name }}
diff --git a/server/tests/server.rs b/server/tests/server.rs index fb050aa..9c5a39b 100644 --- a/server/tests/server.rs +++ b/server/tests/server.rs @@ -30,7 +30,8 @@ pub async fn test_server_listens() { .unwrap() .into_string() .unwrap(); - assert_eq!(response, "Hello World!") + assert!(response.contains("")); + assert!(response.contains("test")) }) .await .unwrap();