From 9edcd1896de834ab0fdec7560a4aa006469d6948 Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Fri, 10 Nov 2023 23:30:58 -0600 Subject: [PATCH] Whee stuff is happening --- Cargo.lock | 161 +++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 3 + assets/styles.css | 170 ++++++++++++++++++++++++++++++++++++++++++++++ contract.hurl | 11 +++ flake.nix | 1 + src/main.rs | 93 ++++++++++++++++++++++--- 6 files changed, 424 insertions(+), 15 deletions(-) create mode 100644 assets/styles.css diff --git a/Cargo.lock b/Cargo.lock index 2fe44ff..4202bab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + [[package]] name = "async-trait" version = "0.1.74" @@ -34,7 +40,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", ] [[package]] @@ -51,7 +57,7 @@ checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", "axum-core", - "bitflags", + "bitflags 1.3.2", "bytes", "futures-util", "http", @@ -113,6 +119,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + [[package]] name = "bytes" version = "1.5.0" @@ -164,6 +176,12 @@ version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +[[package]] +name = "futures-sink" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" + [[package]] name = "futures-task" version = "0.3.29" @@ -216,6 +234,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-range-header" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" + [[package]] name = "httparse" version = "1.8.0" @@ -289,9 +313,12 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" name = "lyrs" version = "0.1.0" dependencies = [ + "anyhow", "axum", + "maud", "serde", "tokio", + "tower-http", "tracing", "tracing-subscriber", ] @@ -311,6 +338,28 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +[[package]] +name = "maud" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0bab19cef8a7fe1c18a43e881793bfc9d4ea984befec3ae5bd0415abf3ecf00" +dependencies = [ + "itoa", + "maud_macros", +] + +[[package]] +name = "maud_macros" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0be95d66c3024ffce639216058e5bae17a83ecaf266ffc6e4d060ad447c9eed2" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "memchr" version = "2.6.4" @@ -323,6 +372,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -430,7 +489,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", ] [[package]] @@ -445,6 +504,30 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" version = "1.0.69" @@ -469,7 +552,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -557,7 +640,7 @@ checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", ] [[package]] @@ -637,6 +720,17 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.39" @@ -691,7 +785,20 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", ] [[package]] @@ -710,6 +817,31 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-http" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" +dependencies = [ + "bitflags 2.4.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "httpdate", + "mime", + "mime_guess", + "percent-encoding", + "pin-project-lite", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower-layer" version = "0.3.2" @@ -742,7 +874,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.39", ] [[package]] @@ -790,6 +922,15 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-ident" version = "1.0.12" @@ -802,6 +943,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "want" version = "0.3.1" diff --git a/Cargo.toml b/Cargo.toml index c4f285c..0e78f1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,8 +4,11 @@ version = "0.1.0" edition = "2021" [dependencies] +anyhow = "1.0.75" axum = "0.6.20" +maud = "0.25.0" serde = { version = "1.0.192", features = ["derive"] } tokio = { version = "1.34.0", features = ["full"] } +tower-http = { version = "0.4.4", features = ["fs"] } tracing = "0.1.40" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/assets/styles.css b/assets/styles.css new file mode 100644 index 0000000..b67acd4 --- /dev/null +++ b/assets/styles.css @@ -0,0 +1,170 @@ +/* reset */ + +html { + box-sizing: border-box; +} + +*, +*::before, +*::after { + box-sizing: inherit; +} + +html { + -moz-text-size-adjust: none; + -webkit-text-size-adjust: none; + text-size-adjust: none; +} + +body, +h1, +h2, +h3, +h4, +h5, +h6, +p, +figure, +blockquote, +dl, +dd { + margin: 0; +} + +ul[class], +ol[class] { + margin: 0; + padding: 0; + list-style: none; +} + +html { + line-height: 1.5; +} + +body { + min-height: 100dvh; +} + +h1, +h2, +h3, +h4, +h5, +h6, +button, +input, +label { + line-height: 1.1; +} + +h1, +h2, +h3, +h4 { + text-wrap: balance; +} + +img, +picture { + max-width: 100%; + display: block; +} + +input, +button, +textarea, +select { + font: inherit; +} + +textarea:not([rows]) { + min-height: 10em; + /* form-sizing: normal; */ +} + +:target { + scroll-margin-block: 5ex; +} + +a[class] { + color: currentColor; +} + +/* end reset */ + +/* global classes */ + +.flex { + display: flex; +} + +.flex-col { + flex-direction: column; +} + +/* end global classes */ + +:root { + --font: monospace; + + --bg: #fff; + --bg2: #eee; + --primary: #8b5cf6; + --text: #111; + --link: #04f; +} + +@media (prefers-color-scheme: dark) { + :root { + --bg: #111; + --bg2: #222; + --primary: #8b5cf6; + --text: #ccc; + --link: #0af; + --link-visited: #faf; + } +} + +a:not([class]) { + color: var(--link); +} + +a:not([class]):visited { + color: var(--link-visited); +} + +a.primary { + color: var(--primary); + text-decoration: none; +} + +html { + background-color: var(--bg); + color: var(--text); + font-family: var(--font); + font-size: 16px; +} + +body>header { + justify-content: space-between; + /* border-bottom: solid 1px var(--bg2); */ + background-color: var(--bg); + box-shadow: 0 -1px 1ex rgba(0, 0, 0, 0.5); +} + +body>header>nav { + justify-content: space-between; +} + +body>header a { + display: flex; + align-items: center; + padding: 1ex; + transition: color 0.1s ease-out, background-color 0.1s ease-out; +} + +body>header a:hover { + background-color: var(--primary); + color: var(--bg); +} \ No newline at end of file diff --git a/contract.hurl b/contract.hurl index d8dddb2..87f1968 100644 --- a/contract.hurl +++ b/contract.hurl @@ -1,2 +1,13 @@ GET {{base}} HTTP 404 +content-length: 0 + +GET {{base}}/hello-world +HTTP 200 +Content-Type: text/html; charset=utf-8 +

Hello, world!

+ +GET {{base}}/hello-world-text +HTTP 200 +Content-Type: text/plain; charset=utf-8 +"Hello, world!" diff --git a/flake.nix b/flake.nix index 5ecf97a..c186c9f 100644 --- a/flake.nix +++ b/flake.nix @@ -47,6 +47,7 @@ rustfmt rustPackages.clippy rust-analyzer + nodePackages_latest.vscode-langservers-extracted ]; RUST_SRC_PATH = rustPlatform.rustLibSrc; }; diff --git a/src/main.rs b/src/main.rs index 3e39294..d462b10 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,27 +1,104 @@ //! lyrs entrypoint use axum::{response::Html, routing::get, Router}; +use maud::html; use std::net::SocketAddr; -use tracing::info; +use tower_http::services::ServeDir; +use tracing::{info, instrument, trace}; +use tracing_subscriber::{ + filter::{Directive, LevelFilter}, + EnvFilter, +}; -#[tokio::main] -async fn main() { - tracing_subscriber::fmt().init(); - let app = Router::new() +fn setup_trace_logger() { + let default_filter: Result = + Ok(EnvFilter::builder() + .with_default_directive(LevelFilter::INFO.into()) + .parse("info") + .unwrap()); + + let default_directive: Result = + "lyrs=trace".parse(); + + if default_directive.is_err() { + println!("{:?}", default_directive); + } + + let filter = EnvFilter::try_from_env("LOG_FILTER") + .or(default_filter) + .unwrap() + .add_directive(LevelFilter::INFO.into()) + .add_directive("lyrs=trace".parse().unwrap()); + + tracing_subscriber::fmt().with_env_filter(filter).init(); + + trace!("Starting..."); +} + +fn router() -> Router { + let app_router = Router::new() .route("/hello-world", get(greet_world)) .route("/hello-world-text", get(greet_world_text)); + + let assets_dir = ServeDir::new("./assets"); + + Router::new() + .nest("/app", app_router) + .nest_service("/assets", assets_dir) + .route("/", get(index)) +} + +async fn listen(r: Router) { let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); info!("Listening on '{}'", addr); axum::Server::bind(&addr) - .serve(app.into_make_service()) + .serve(r.into_make_service()) .await .unwrap(); } -async fn greet_world() -> Html<&'static str> { - Html("

Hello, World!

") +#[tokio::main] +async fn main() { + setup_trace_logger(); + listen(router()).await; } +#[instrument] +async fn index() -> Html { + Html( + html! { + head { + link rel="stylesheet" href="/assets/styles.css" {} + } + header class="flex" { + nav class="flex" { + h1 { + a class="primary" href="/" { "lyrs" } + } + } + nav class="flex" { + ul class="flex" + { + a class="primary" href="/login" { "Login" } + } + } + } + } + .into_string(), + ) +} + +#[instrument] +async fn greet_world() -> Html { + Html( + html! { + h1 { (greet_world_text().await) } + } + .into_string(), + ) +} + +#[instrument] async fn greet_world_text() -> &'static str { "Hello, World!" }