From a09684c075628c4555a2f92a68f1b93192d90510 Mon Sep 17 00:00:00 2001 From: ramiroaisen <52116153+ramiroaisen@users.noreply.github.com> Date: Wed, 21 Jun 2023 15:01:12 -0300 Subject: [PATCH] change static to rust-embed based solution --- Cargo.lock | 249 ++++++++++++++++-- Cargo.toml | 1 + mailer-static/config.toml | 67 ----- mailer-static/pm2.config.cjs | 16 -- openstream.sample.jsonc | 7 + openstream.sample.toml | 8 + rs/bin/openstream/Cargo.toml | 1 + rs/bin/openstream/src/main.rs | 15 ++ rs/packages/assets/Cargo.toml | 23 ++ rs/packages/assets/src/lib.rs | 171 ++++++++++++ rs/packages/config/src/lib.rs | 16 +- rs/packages/mailer/templates/base.html | 2 +- scripts/src/release.mts | 1 - .../static/email}/v1/top-logo.png | Bin .../public => static/static}/robots.txt | 0 .../public => static/static}/status.txt | 0 16 files changed, 462 insertions(+), 115 deletions(-) delete mode 100644 mailer-static/config.toml delete mode 100644 mailer-static/pm2.config.cjs create mode 100644 rs/packages/assets/Cargo.toml create mode 100644 rs/packages/assets/src/lib.rs rename {mailer-static/public => static/static/email}/v1/top-logo.png (100%) rename {mailer-static/public => static/static}/robots.txt (100%) rename {mailer-static/public => static/static}/status.txt (100%) diff --git a/Cargo.lock b/Cargo.lock index e0043a44..6cbd9d98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -73,6 +73,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -116,7 +131,7 @@ dependencies = [ "mailer", "media-sessions", "mongodb", - "owo-colors", + "owo-colors 3.5.0", "parking_lot 0.12.1", "payments", "prex", @@ -207,6 +222,27 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" +[[package]] +name = "assets" +version = "0.1.0" +dependencies = [ + "async-trait", + "base64-compat", + "futures-util", + "http 0.1.0", + "hyper", + "log", + "mime_guess", + "owo-colors 3.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "prex", + "rust-embed", + "rust-embed-for-web", + "shutdown", + "socket2 0.5.3", + "thiserror", + "tokio", +] + [[package]] name = "ast_node" version = "0.8.6" @@ -320,9 +356,24 @@ checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5" [[package]] name = "base64" -version = "0.21.0" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" + +[[package]] +name = "base64-compat" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +checksum = "5a8d4d2746f89841e49230dd26917df1876050f95abafafbe34f47cb534b88d7" +dependencies = [ + "byteorder", +] + +[[package]] +name = "base85rs" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7b7172542a3d446ca7b2be4e28e4f4c119a89c396712f7ca1ad2822bfc54ca2" [[package]] name = "basic-toml" @@ -388,6 +439,27 @@ dependencies = [ "cipher", ] +[[package]] +name = "brotli" +version = "3.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b6561fd3f895a11e8f72af2cb7d22e08366bebc2b6b57f7744c4bda27034744" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + [[package]] name = "bson" version = "2.5.0" @@ -405,6 +477,16 @@ dependencies = [ "uuid", ] +[[package]] +name = "bstr" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "bumpalo" version = "3.11.1" @@ -714,7 +796,7 @@ dependencies = [ "log", "logger", "mongodb", - "owo-colors", + "owo-colors 3.5.0", "rand 0.8.5", "serde-util", "thiserror", @@ -735,7 +817,7 @@ dependencies = [ "log", "logger", "mongodb", - "owo-colors", + "owo-colors 3.5.0", "serde-util", "thiserror", "tokio", @@ -1186,6 +1268,26 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "dotenv" version = "0.15.0" @@ -1272,7 +1374,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbfb21b9878cf7a348dcb8559109aabc0ec40d69924bd706fa5149846c4fef75" dependencies = [ - "base64 0.21.0", + "base64 0.21.2", "memchr", ] @@ -1648,6 +1750,19 @@ dependencies = [ "weezl", ] +[[package]] +name = "globset" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + [[package]] name = "h2" version = "0.3.17" @@ -2304,7 +2419,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76bd09637ae3ec7bd605b8e135e757980b3968430ff2b1a4a94fb7769e50166d" dependencies = [ "async-trait", - "base64 0.21.0", + "base64 0.21.2", "email-encoding", "email_address", "fastrand", @@ -2469,12 +2584,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "logger" @@ -2484,7 +2596,7 @@ dependencies = [ "crossterm", "env_logger", "log", - "owo-colors", + "owo-colors 3.5.0", "static_init", "time 0.3.20", ] @@ -2661,7 +2773,7 @@ dependencies = [ "logger", "macros", "mongodb", - "owo-colors", + "owo-colors 3.5.0", "serde", "serde-util", "tokio", @@ -2863,6 +2975,16 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +[[package]] +name = "new_mime_guess" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2d684d1b59e0dc07b37e2203ef576987473288f530082512aff850585c61b1f" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -3001,6 +3123,7 @@ version = "0.1.0" dependencies = [ "anyhow", "api", + "assets", "chrono", "clap", "config", @@ -3019,7 +3142,7 @@ dependencies = [ "mailer", "media-sessions", "mongodb", - "owo-colors", + "owo-colors 3.5.0", "payments", "serde-util", "shutdown", @@ -3051,6 +3174,12 @@ dependencies = [ "supports-color", ] +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + [[package]] name = "parking_lot" version = "0.3.8" @@ -3664,6 +3793,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom 0.2.8", + "redox_syscall 0.2.16", + "thiserror", +] + [[package]] name = "regex" version = "1.7.0" @@ -3742,7 +3882,7 @@ version = "0.11.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" dependencies = [ - "base64 0.21.0", + "base64 0.21.2", "bytes", "encoding_rs", "futures-core", @@ -3856,7 +3996,7 @@ dependencies = [ "hyper", "log", "mongodb", - "owo-colors", + "owo-colors 3.5.0", "prex", "serde", "shutdown", @@ -3867,25 +4007,67 @@ dependencies = [ [[package]] name = "rust-embed" -version = "6.6.1" +version = "6.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b68543d5527e158213414a92832d2aab11a84d2571a5eb021ebe22c43aab066" +checksum = "b73e721f488c353141288f223b599b4ae9303ecf3e62923f40a492f0634a4dc3" dependencies = [ "rust-embed-impl", "rust-embed-utils", "walkdir", ] +[[package]] +name = "rust-embed-for-web" +version = "11.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bfea1a9dd0901c9179d058c4666b6c3834b11e6934ea2ea639f64ca63b344f" +dependencies = [ + "rust-embed-for-web-impl", + "rust-embed-for-web-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-for-web-impl" +version = "11.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "903f58bad1c5b4e348b3b3ef006ef3ad930a8a66f3ba0d5671c71223e28d6862" +dependencies = [ + "brotli", + "flate2", + "globset", + "proc-macro2", + "quote", + "rust-embed-for-web-utils", + "shellexpand", + "syn 1.0.107", + "walkdir", +] + +[[package]] +name = "rust-embed-for-web-utils" +version = "11.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f666d8ab11fddb37e3d36c353251ee2b1b5f96a87a5ef81c7f6f25c5e4ab2ccc" +dependencies = [ + "base85rs", + "chrono", + "globset", + "new_mime_guess", + "sha2", + "walkdir", +] + [[package]] name = "rust-embed-impl" -version = "6.5.0" +version = "6.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4e0f0ced47ded9a68374ac145edd65a6c1fa13a96447b873660b2a568a0fd7" +checksum = "e22ce362f5561923889196595504317a4372b84210e6e335da529a65ea5452b5" dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 1.0.107", + "syn 2.0.13", "walkdir", ] @@ -4260,6 +4442,15 @@ dependencies = [ "digest", ] +[[package]] +name = "shellexpand" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4" +dependencies = [ + "dirs", +] + [[package]] name = "shutdown" version = "0.1.0" @@ -4366,9 +4557,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d283f86695ae989d1e18440a943880967156325ba025f05049946bff47bcc2b" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" dependencies = [ "libc", "windows-sys 0.48.0", @@ -4390,7 +4581,7 @@ dependencies = [ "media-sessions", "mongodb", "once_cell", - "owo-colors", + "owo-colors 3.5.0", "parking_lot 0.12.1", "prex", "proxy-protocol", @@ -4400,7 +4591,7 @@ dependencies = [ "serde-util", "serde_qs", "shutdown", - "socket2 0.5.2", + "socket2 0.5.3", "static_init", "stream-util", "thiserror", @@ -4496,7 +4687,7 @@ dependencies = [ "log", "media-sessions", "mongodb", - "owo-colors", + "owo-colors 3.5.0", "parking_lot 0.12.1", "prex", "rand 0.8.5", @@ -4985,9 +5176,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.28.1" +version = "1.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" +checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" dependencies = [ "autocfg", "bytes", diff --git a/Cargo.toml b/Cargo.toml index 9a887e6c..74393934 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ members = [ "rs/packages/stream", "rs/packages/source-alt", "rs/packages/stream", + "rs/packages/assets", "rs/packages/router", "rs/packages/upload", "rs/packages/api", diff --git a/mailer-static/config.toml b/mailer-static/config.toml deleted file mode 100644 index 37c4bf5d..00000000 --- a/mailer-static/config.toml +++ /dev/null @@ -1,67 +0,0 @@ -[general] - -#### Address & Root dir -host = "::" -port = 11000 -root = "./public" - -#### Logging -log-level = "info" - -#### Cache Control headers -cache-control-headers = true - -#### Auto Compression -compression = true - -#### Error pages -# page404 = "./public/404.html" -# page50x = "./public/50x.html" - -#### HTTP/2 + TLS -http2 = false -# http2-tls-cert = "some.cert" -# http2-tls-key = "some.key" - -#### Security headers -security-headers = true - -#### CORS -# cors-allow-origins = "" -# cors-allow-headers = "" - -#### Directory listing -directory-listing = false - -#### Directory listing sorting code -directory-listing-order = 6 - -#### Directory listing content format ("html" or "json") -# directory-listing-format = "html" - -#### Basich Authentication -# basic-auth = "" - -#### File descriptor binding -# fd = "" - -#### Worker threads -threads-multiplier = 1 - -#### Grace period after a graceful shutdown -grace-period = 0 - -#### Page fallback for 404s -# page-fallback = "some_page.html" - -#### Log request Remote Address if available -log-remote-address = false - -#### Redirect to trailing slash in the requested directory uri -redirect-trailing-slash = true - -#### Check for existing pre-compressed files -compression-static = false - -#### Ignore hidden files/directories (dotfiles) -ignore-hidden-files = true \ No newline at end of file diff --git a/mailer-static/pm2.config.cjs b/mailer-static/pm2.config.cjs deleted file mode 100644 index f8d86714..00000000 --- a/mailer-static/pm2.config.cjs +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - apps: [ - { - name: "mailer-static", - exec_mode: "fork", - script: "static-web-server", - args: ["-w", "config.toml"], - instances: 1, - kill_timeout: 10_000, - env: { - RUST_LOG_STYLE: "always", - FORCE_COLOR: "1", - }, - }, - ], -}; diff --git a/openstream.sample.jsonc b/openstream.sample.jsonc index 2c369ce9..9729784b 100644 --- a/openstream.sample.jsonc +++ b/openstream.sample.jsonc @@ -42,6 +42,13 @@ "addrs": [ "0.0.0.0:10900" ] }, + // the [static] server is the interface to the static files server + "static": { + // string(SocketAddr)[] (required) + // socket addrs to bind the assets server to + "addrs": [ "0.0.0.0:11000" ] + }, + // payments server configuration "payments": { diff --git a/openstream.sample.toml b/openstream.sample.toml index a87fa2bb..d827b8e7 100644 --- a/openstream.sample.toml +++ b/openstream.sample.toml @@ -38,6 +38,14 @@ addrs = [ "0.0.0.0:10700" ] # socket addrs to bind the api server to addrs = [ "0.0.0.0:10900" ] +# the [assets] server is the interface to the static files server +[static] + +# string(SocketAddr)[] (required) +# socket addrs to bind the assets server to +addrs = [ "0.0.0.0:11000" ] + + # payments server configuration [payments] diff --git a/rs/bin/openstream/Cargo.toml b/rs/bin/openstream/Cargo.toml index a33cc6da..dd2464a9 100644 --- a/rs/bin/openstream/Cargo.toml +++ b/rs/bin/openstream/Cargo.toml @@ -40,3 +40,4 @@ hyper = "0.14.26" validate = { version = "0.1.0", path = "../../packages/validate" } mailer = { version = "0.1.0", path = "../../packages/mailer" } payments = { version = "0.1.0", path = "../../packages/payments" } +assets = { version = "0.1.0", path = "../../packages/assets" } diff --git a/rs/bin/openstream/src/main.rs b/rs/bin/openstream/src/main.rs index cb82db31..c4e08697 100644 --- a/rs/bin/openstream/src/main.rs +++ b/rs/bin/openstream/src/main.rs @@ -25,6 +25,7 @@ use serde_util::DateTime; use shutdown::Shutdown; // use source::SourceServer; use stream::StreamServer; +use assets::StaticServer; use tokio::runtime::Runtime; use jemallocator::Jemalloc; @@ -371,6 +372,7 @@ async fn start_async(Start { config }: Start) -> Result<(), anyhow::Error> { ref source, ref api, ref storage, + ref assets, ref smtp, ref payments, } = config.as_ref(); @@ -468,6 +470,19 @@ async fn start_async(Start { config }: Start) -> Result<(), anyhow::Error> { }.boxed()); } + if let Some(static_config) = assets { + let assets = StaticServer::new( + static_config.addrs.clone(), + shutdown.clone(), + ); + let fut = assets.start()?; + futs.push(async move { + fut.await.map_err(crate::error::ServerStartError::from)?; + Ok(()) + }.boxed()); + } + + // if let Some(router_config) = router { // let router = RouterServer::new(router_config.addrs.clone(), shutdown.clone()); // let fut = router.start()?; diff --git a/rs/packages/assets/Cargo.toml b/rs/packages/assets/Cargo.toml new file mode 100644 index 00000000..646d49cd --- /dev/null +++ b/rs/packages/assets/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "assets" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +async-trait = "0.1.68" +base64-compat = "1.0.0" +futures-util = "0.3.28" +http = { version = "0.1.0", path = "../http" } +hyper = "0.14.26" +log = "0.4.19" +mime_guess = "2.0.4" +owo-colors = "3.5.0" +prex = { version = "0.1.0", path = "../prex" } +rust-embed = { version = "6.7.0", features = ["debug-embed"] } +rust-embed-for-web = "11.1.1" +shutdown = { version = "0.1.0", path = "../shutdown" } +socket2 = "0.5.3" +thiserror = "1.0.40" +tokio = { version = "1.28.2", features = ["full"] } diff --git a/rs/packages/assets/src/lib.rs b/rs/packages/assets/src/lib.rs new file mode 100644 index 00000000..e5b609ba --- /dev/null +++ b/rs/packages/assets/src/lib.rs @@ -0,0 +1,171 @@ +#![allow(clippy::useless_format)] + +use async_trait::async_trait; +use futures_util::stream::{FuturesUnordered, TryStreamExt}; +use hyper::header::{HeaderValue, CONTENT_TYPE, ETAG, IF_NONE_MATCH}; +use hyper::{Body, Server, StatusCode}; +use log::*; +use prex::{handler::Handler, Next, Request, Response}; +use rust_embed::RustEmbed; +use shutdown::Shutdown; +use socket2::{Domain, Protocol, Socket, Type}; +use std::future::Future; +use std::net::SocketAddr; + +#[derive(RustEmbed)] +#[folder = "../../../static/static/"] +struct Assets; + +#[derive(Debug, thiserror::Error)] +pub enum StaticServerError { + #[error("io error: {0}")] + Io(#[from] std::io::Error), + #[error("hyper error: {0}")] + Hyper(#[from] hyper::Error), +} + +#[derive(Debug)] +pub struct StaticServer { + addrs: Vec, + shutdown: Shutdown, +} + +#[derive(Debug)] +struct SourceServerInner {} + +impl StaticServer { + pub fn new(addrs: Vec, shutdown: Shutdown) -> Self { + Self { addrs, shutdown } + } + + pub fn start( + self, + ) -> Result> + 'static, StaticServerError> { + let mut app = prex::prex(); + + app.with(http::middleware::server); + app.get("/status", http::middleware::status); + app.get("/:path(.+)", StaticHandler::new()); + + let app = app.build().expect("prex app build source"); + + let futs = FuturesUnordered::new(); + + for addr in self.addrs.iter().cloned() { + let domain = match addr { + SocketAddr::V4(_) => Domain::IPV4, + SocketAddr::V6(_) => Domain::IPV6, + }; + + let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?; + + if addr.is_ipv6() { + socket.set_only_v6(true)?; + } + + socket.set_nonblocking(true)?; + socket.set_reuse_address(true)?; + // socket.set_reuse_port(true)?; + + match socket.bind(&addr.into()) { + Ok(()) => {} + Err(e) => { + error!("error binding to addr {} => {}", addr, e); + return Err(e.into()); + } + }; + + socket.listen(1024)?; + + let tcp = socket.into(); + + let server = Server::from_tcp(tcp)? + .http1_only(true) + .http1_title_case_headers(false) + .http1_preserve_header_case(false) + .http1_keepalive(false); + + { + use owo_colors::*; + info!("static server bound to {}", addr.yellow()); + } + + futs.push({ + let signal = self.shutdown.signal(); + let server = server.serve(app.clone()); + + async move { + tokio::select! { + _ = signal => Ok(()), + r = server => r + } + } + }); + + // server + // .serve(app.clone()) + // .with_graceful_shutdown(self.shutdown.signal()), + // ) + } + + Ok(async move { + futs.try_collect().await?; + drop(self); + Ok(()) + }) + } +} + +impl Drop for StaticServer { + fn drop(&mut self) { + info!("static server dropped"); + } +} + +pub struct StaticHandler {} + +impl StaticHandler { + fn new() -> Self { + Self {} + } + + async fn handle(&self, req: Request) -> prex::Response { + let path = req.param("path").unwrap(); + + let entry = match Assets::get(path) { + None => return prex::Response::new(StatusCode::NOT_FOUND), + Some(entry) => entry, + }; + + let etag = format!(r#""{}""#, base64::encode(&entry.metadata.sha256_hash())); + + if let Some(req_etag) = req.headers().get(IF_NONE_MATCH) { + if req_etag.as_bytes() == etag.as_bytes() { + return prex::Response::new(StatusCode::NOT_MODIFIED); + } + } + + let mut res = Response::new(StatusCode::OK); + + let content_type = match mime_guess::from_path(path).first() { + Some(mime) => HeaderValue::from_str(mime.as_ref()).unwrap(), + None => HeaderValue::from_static("application/octet-stream"), + }; + + let etag = HeaderValue::from_str(&etag).unwrap(); + + res.headers_mut().insert(CONTENT_TYPE, content_type); + res.headers_mut().insert(ETAG, etag); + + *res.body_mut() = Body::from(entry.data); + + res + } +} + +#[async_trait] +impl Handler for StaticHandler { + async fn call(&self, req: Request, _: Next) -> prex::Response { + self.handle(req).await + } +} diff --git a/rs/packages/config/src/lib.rs b/rs/packages/config/src/lib.rs index 58f8ce65..7cecbdeb 100644 --- a/rs/packages/config/src/lib.rs +++ b/rs/packages/config/src/lib.rs @@ -11,13 +11,21 @@ pub struct Config { // pub router: Option, pub api: Option, pub storage: Option, + + #[serde(rename = "static")] + pub assets: Option, + pub smtp: Smtp, pub payments: Payments, } impl Config { pub fn has_interfaces(&self) -> bool { - self.stream.is_some() || self.source.is_some() || self.api.is_some() || self.storage.is_some() + self.stream.is_some() + || self.source.is_some() + || self.api.is_some() + || self.storage.is_some() + || self.assets.is_some() } } @@ -43,6 +51,12 @@ pub struct Stream { pub addrs: Vec, } +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub struct Static { + pub addrs: Vec, +} + #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] #[serde(deny_unknown_fields)] pub struct Source { diff --git a/rs/packages/mailer/templates/base.html b/rs/packages/mailer/templates/base.html index 4f3c87af..e802c708 100644 --- a/rs/packages/mailer/templates/base.html +++ b/rs/packages/mailer/templates/base.html @@ -47,7 +47,7 @@ diff --git a/scripts/src/release.mts b/scripts/src/release.mts index 81d62e2f..3099a58f 100644 --- a/scripts/src/release.mts +++ b/scripts/src/release.mts @@ -59,7 +59,6 @@ for(const dir of ["server", "app", "admin"]) { } await $`cp -r ${`${basedir}/static`} ${`${tmpdir}/static`}`; -await $`cp -r ${`${basedir}/mailer-static`} ${`${tmpdir}/mailer-static`}`; await $`cp ${`${basedir}/openstream-front.mjs`} ${`${tmpdir}/openstream-front.mjs`}`; await $`cp ${binfile.src} ${binfile.target}`; diff --git a/mailer-static/public/v1/top-logo.png b/static/static/email/v1/top-logo.png similarity index 100% rename from mailer-static/public/v1/top-logo.png rename to static/static/email/v1/top-logo.png diff --git a/mailer-static/public/robots.txt b/static/static/robots.txt similarity index 100% rename from mailer-static/public/robots.txt rename to static/static/robots.txt diff --git a/mailer-static/public/status.txt b/static/static/status.txt similarity index 100% rename from mailer-static/public/status.txt rename to static/static/status.txt