From 96e84fcea452594981b49bfd5ecb35047d2dc100 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Wed, 20 Nov 2024 19:59:28 -0300 Subject: [PATCH 1/3] feat(server): re-structure server logic to have middleware applied optionally --- Cargo.lock | 155 +++++++++++++++--- Cargo.toml | 4 +- crates/file-explorer/src/lib.rs | 2 +- crates/http-server/Cargo.toml | 12 +- .../src/{ => bin}/cli/command/mod.rs | 0 .../src/{ => bin}/cli/command/start.rs | 4 +- crates/http-server/src/{ => bin}/cli/mod.rs | 0 crates/http-server/src/{ => bin}/main.rs | 3 - crates/http-server/src/config.rs | 10 -- crates/http-server/src/lib.rs | 1 + crates/http-server/src/server/config.rs | 37 +++++ .../src/{server.rs => server/mod.rs} | 33 ++-- crates/http-server/src/{ => server}/plugin.rs | 0 13 files changed, 211 insertions(+), 50 deletions(-) rename crates/http-server/src/{ => bin}/cli/command/mod.rs (100%) rename crates/http-server/src/{ => bin}/cli/command/start.rs (94%) rename crates/http-server/src/{ => bin}/cli/mod.rs (100%) rename crates/http-server/src/{ => bin}/main.rs (87%) delete mode 100644 crates/http-server/src/config.rs create mode 100644 crates/http-server/src/lib.rs create mode 100644 crates/http-server/src/server/config.rs rename crates/http-server/src/{server.rs => server/mod.rs} (79%) rename crates/http-server/src/{ => server}/plugin.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index fc55de5d..b19ec973 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "aho-corasick" version = "1.1.3" @@ -26,6 +32,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-tzdata" version = "0.1.1" @@ -96,6 +117,22 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +[[package]] +name = "async-compression" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cb8f1d480b0ea3783ab015936d2a55c87e219676f0c0b7dec61494043f21857" +dependencies = [ + "brotli", + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", + "zstd", + "zstd-safe", +] + [[package]] name = "async-recursion" version = "1.1.1" @@ -170,17 +207,11 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.5.1", "object", "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - [[package]] name = "base64" version = "0.22.1" @@ -217,6 +248,27 @@ dependencies = [ "generic-array", ] +[[package]] +name = "brotli" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -247,6 +299,8 @@ version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" dependencies = [ + "jobserver", + "libc", "shlex", ] @@ -428,6 +482,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + [[package]] name = "crunchy" version = "0.2.2" @@ -587,6 +650,16 @@ dependencies = [ "web-sys", ] +[[package]] +name = "flate2" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +dependencies = [ + "crc32fast", + "miniz_oxide 0.8.0", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1021,15 +1094,6 @@ dependencies = [ "itoa", ] -[[package]] -name = "http-auth-basic" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd2e17aacf7f4a2428def798e2ff4f4f883c0987bdaf47dd5c8bc027bc9f1ebc" -dependencies = [ - "base64 0.13.0", -] - [[package]] name = "http-body" version = "1.0.1" @@ -1062,7 +1126,6 @@ dependencies = [ "bytes", "clap", "http 1.1.0", - "http-auth-basic", "http-body-util", "http-server-plugin", "hyper", @@ -1072,6 +1135,7 @@ dependencies = [ "tokio", "tower", "tower-http", + "tower-layer", "tracing", "tracing-subscriber", ] @@ -1268,6 +1332,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.72" @@ -1407,7 +1480,7 @@ version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4161acbf80f59219d8d14182371f57302bc7ff81ee41aba8ba1ff7295727f23" dependencies = [ - "base64 0.22.1", + "base64", "cfg-if", "futures", "indexmap", @@ -1615,6 +1688,15 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" version = "1.0.2" @@ -2084,7 +2166,7 @@ version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ - "base64 0.22.1", + "base64", "bytes", "encoding_rs", "futures-core", @@ -2831,10 +2913,17 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8437150ab6bbc8c5f0f519e3d5ed4aa883a83dd4cdd3d1b21f9482936046cb97" dependencies = [ + "async-compression", + "base64", "bitflags 2.4.0", "bytes", + "futures-core", "http 1.1.0", + "http-body", + "mime", "pin-project-lite", + "tokio", + "tokio-util", "tower-layer", "tower-service", ] @@ -3371,3 +3460,31 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zstd" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.13+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index 6b2781e0..78343e01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,6 @@ gloo = "0.11.0" gloo-file = "0.3.0" humansize = "2.1.3" http = "1.1.0" -http-auth-basic = "0.3.3" http-body-util = "0.1" hyper = "1.4" hyper-util = "0.1.9" @@ -44,8 +43,9 @@ serde_json = "1.0.128" tokio = "1.40" tokio-util = "0.7.12" toml = "0.8.19" -tower-http = "0.6.1" tower = "0.5.1" +tower-http = "0.6.1" +tower-layer = "0.3.3" tracing = "0.1.40" tracing-subscriber = "0.3.18" web-sys = "0.3.72" diff --git a/crates/file-explorer/src/lib.rs b/crates/file-explorer/src/lib.rs index a8f21422..b0e21317 100644 --- a/crates/file-explorer/src/lib.rs +++ b/crates/file-explorer/src/lib.rs @@ -113,7 +113,7 @@ impl FileExplorerPlugin { let body = Full::new(Bytes::from(index.data.to_vec())); let mut response = Response::new(body); let mut headers = response.headers().clone(); - + println!("{headers:?}"); headers.append(CONTENT_TYPE, "text/html".try_into().unwrap()); *response.headers_mut() = headers; diff --git a/crates/http-server/Cargo.toml b/crates/http-server/Cargo.toml index 755d7047..01cec9df 100644 --- a/crates/http-server/Cargo.toml +++ b/crates/http-server/Cargo.toml @@ -10,6 +10,14 @@ keywords = ["configurable", "http", "server", "serve", "static"] license = "MIT OR Apache-2.0" readme = "README.md" +[[bin]] +name = "http-server" +path = "src/bin/main.rs" + +[lib] +name = "http_server_rs" +path = "src/lib.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] @@ -18,15 +26,15 @@ async-trait = { workspace = true } bytes = { workspace = true } clap = { workspace = true, features = ["env", "derive", "std"] } http = { workspace = true } -http-auth-basic = { workspace = true } http-body-util = { workspace = true } hyper = { workspace = true } hyper-util = { workspace = true, features = ["full"] } libloading = { workspace = true } local-ip-address = { workspace = true } tokio = { workspace = true, features = ["fs", "rt-multi-thread", "signal", "macros"] } -tower-http = { workspace = true, features = ["cors"] } +tower-http = { workspace = true, features = ["auth", "cors", "compression-full"] } tower = { workspace = true, features = ["util"] } +tower-layer = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } diff --git a/crates/http-server/src/cli/command/mod.rs b/crates/http-server/src/bin/cli/command/mod.rs similarity index 100% rename from crates/http-server/src/cli/command/mod.rs rename to crates/http-server/src/bin/cli/command/mod.rs diff --git a/crates/http-server/src/cli/command/start.rs b/crates/http-server/src/bin/cli/command/start.rs similarity index 94% rename from crates/http-server/src/cli/command/start.rs rename to crates/http-server/src/bin/cli/command/start.rs index 0ea5fc7b..56cbaf97 100644 --- a/crates/http-server/src/cli/command/start.rs +++ b/crates/http-server/src/bin/cli/command/start.rs @@ -7,8 +7,8 @@ use clap::Parser; use tokio::runtime::Builder; use tracing::{error, info}; -use crate::config::Config; -use crate::server::Server; +use http_server_rs::server::config::Config; +use http_server_rs::server::Server; const THREAD_NAME: &str = "http-server"; diff --git a/crates/http-server/src/cli/mod.rs b/crates/http-server/src/bin/cli/mod.rs similarity index 100% rename from crates/http-server/src/cli/mod.rs rename to crates/http-server/src/bin/cli/mod.rs diff --git a/crates/http-server/src/main.rs b/crates/http-server/src/bin/main.rs similarity index 87% rename from crates/http-server/src/main.rs rename to crates/http-server/src/bin/main.rs index ced279e9..63c2ddf2 100644 --- a/crates/http-server/src/main.rs +++ b/crates/http-server/src/bin/main.rs @@ -1,7 +1,4 @@ pub mod cli; -pub mod config; -pub mod plugin; -pub mod server; use anyhow::Result; use clap::Parser; diff --git a/crates/http-server/src/config.rs b/crates/http-server/src/config.rs deleted file mode 100644 index 11ce1eeb..00000000 --- a/crates/http-server/src/config.rs +++ /dev/null @@ -1,10 +0,0 @@ -use std::net::IpAddr; - -pub struct Config { - /// The IP address to bind to. - pub host: IpAddr, - /// The port to bind to. - pub port: u16, - /// Enable CORS with a permissive policy. - pub cors: bool, -} diff --git a/crates/http-server/src/lib.rs b/crates/http-server/src/lib.rs new file mode 100644 index 00000000..74f47ad3 --- /dev/null +++ b/crates/http-server/src/lib.rs @@ -0,0 +1 @@ +pub mod server; diff --git a/crates/http-server/src/server/config.rs b/crates/http-server/src/server/config.rs new file mode 100644 index 00000000..d3f86f0a --- /dev/null +++ b/crates/http-server/src/server/config.rs @@ -0,0 +1,37 @@ +use std::net::IpAddr; +use std::str::FromStr; + +use anyhow::{bail, Error, Result}; + +#[derive(Clone, Debug)] +pub struct Config { + /// The IP address to bind to. + pub host: IpAddr, + /// The port to bind to. + pub port: u16, + /// Enable CORS with a permissive policy. + pub cors: bool, +} + +#[derive(Clone, Debug)] +pub struct BasicAuth { + pub username: String, + pub password: String, +} + +impl FromStr for BasicAuth { + type Err = Error; + + fn from_str(s: &str) -> Result { + let parts = s.split(":").collect::>(); + + if parts.len() != 2 { + bail!("Expected a string with a colon to separe username and password for Basic Authentication."); + } + + Ok(BasicAuth { + username: parts[0].into(), + password: parts[1].into(), + }) + } +} diff --git a/crates/http-server/src/server.rs b/crates/http-server/src/server/mod.rs similarity index 79% rename from crates/http-server/src/server.rs rename to crates/http-server/src/server/mod.rs index f80b3acc..2c831d66 100644 --- a/crates/http-server/src/server.rs +++ b/crates/http-server/src/server/mod.rs @@ -1,3 +1,6 @@ +pub mod config; +pub mod plugin; + use std::convert::Infallible; use std::net::SocketAddr; use std::path::PathBuf; @@ -6,11 +9,9 @@ use std::sync::Arc; use anyhow::Result; use http_body_util::{BodyExt, Full}; -use hyper::{ - body::{Bytes, Incoming}, - server::conn::http1, - Method, Request, Response, -}; +use hyper::body::{Bytes, Incoming}; +use hyper::server::conn::http1; +use hyper::{Method, Request, Response}; use hyper_util::rt::TokioIo; use hyper_util::service::TowerToHyperService; use tokio::net::TcpListener; @@ -18,8 +19,8 @@ use tokio::runtime::Runtime; use tower::ServiceBuilder; use tower_http::cors::{Any, CorsLayer}; -use crate::config::Config; -use crate::plugin::ExternalFunctions; +use self::config::Config; +use self::plugin::ExternalFunctions; pub struct Server { config: Config, @@ -48,9 +49,18 @@ impl Server { let (stream, _) = listener.accept().await?; let io = TokioIo::new(stream); let functions = Arc::clone(&functions); - let cors = CorsLayer::new() - .allow_methods([Method::GET, Method::POST]) - .allow_origin(Any); + + println!("{:#?}", self.config); + + let cors = if self.config.cors { + Some( + CorsLayer::new() + .allow_methods([Method::GET, Method::POST]) + .allow_origin(Any), + ) + } else { + None + }; handle.spawn(async move { let functions = Arc::clone(&functions); @@ -72,7 +82,8 @@ impl Server { } }); - let svc = ServiceBuilder::new().layer(cors).service(svc); + let svc = ServiceBuilder::new().option_layer(cors).service(svc); + let svc = TowerToHyperService::new(svc); if let Err(err) = http1::Builder::new().serve_connection(io, svc).await { diff --git a/crates/http-server/src/plugin.rs b/crates/http-server/src/server/plugin.rs similarity index 100% rename from crates/http-server/src/plugin.rs rename to crates/http-server/src/server/plugin.rs From fc8ec1fa967d71f3f9120a4b01ce7c92f62b7d00 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Wed, 20 Nov 2024 20:00:08 -0300 Subject: [PATCH 2/3] Update lib.rs --- crates/file-explorer/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/file-explorer/src/lib.rs b/crates/file-explorer/src/lib.rs index b0e21317..a8f21422 100644 --- a/crates/file-explorer/src/lib.rs +++ b/crates/file-explorer/src/lib.rs @@ -113,7 +113,7 @@ impl FileExplorerPlugin { let body = Full::new(Bytes::from(index.data.to_vec())); let mut response = Response::new(body); let mut headers = response.headers().clone(); - println!("{headers:?}"); + headers.append(CONTENT_TYPE, "text/html".try_into().unwrap()); *response.headers_mut() = headers; From 525f7f85a5c82ba5c6e8a313ffcd294bd1ea07d9 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Wed, 20 Nov 2024 20:01:11 -0300 Subject: [PATCH 3/3] Update Cargo.toml --- crates/http-server/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/http-server/Cargo.toml b/crates/http-server/Cargo.toml index 01cec9df..39c71c8a 100644 --- a/crates/http-server/Cargo.toml +++ b/crates/http-server/Cargo.toml @@ -32,7 +32,7 @@ hyper-util = { workspace = true, features = ["full"] } libloading = { workspace = true } local-ip-address = { workspace = true } tokio = { workspace = true, features = ["fs", "rt-multi-thread", "signal", "macros"] } -tower-http = { workspace = true, features = ["auth", "cors", "compression-full"] } +tower-http = { workspace = true, features = ["cors"] } tower = { workspace = true, features = ["util"] } tower-layer = { workspace = true } tracing = { workspace = true }