From f3754b46cf3f8cdeac77daee7d6a0322fbefcf89 Mon Sep 17 00:00:00 2001 From: chaos Date: Wed, 27 Sep 2023 21:40:47 +0100 Subject: [PATCH] Allow more minimal cargo features, tidy code, allow setting unix domain socket filename --- Cargo.lock | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 32 ++++--- src/main.rs | 35 +++++--- 3 files changed, 274 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5318e28..caa142c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -487,6 +487,22 @@ dependencies = [ "version_check", ] +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + [[package]] name = "cpufeatures" version = "0.2.9" @@ -604,6 +620,27 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "exr" version = "1.71.0" @@ -620,6 +657,12 @@ dependencies = [ "zune-inflate", ] +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + [[package]] name = "fdeflate" version = "0.3.0" @@ -654,6 +697,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.0" @@ -891,6 +949,19 @@ dependencies = [ "tokio-rustls", ] +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "idna" version = "0.4.0" @@ -938,9 +1009,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "ad227c3af19d4914570ad36d30409928b75967c298feb9ea1969db3a610bb14e" dependencies = [ "equivalent", "hashbrown 0.14.0", @@ -1011,6 +1082,12 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "lebe" version = "0.5.2" @@ -1053,6 +1130,12 @@ dependencies = [ "glob", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" + [[package]] name = "local-channel" version = "0.1.4" @@ -1172,6 +1255,24 @@ dependencies = [ "rayon", ] +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "new_debug_unreachable" version = "1.0.4" @@ -1283,6 +1384,50 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "openssl" +version = "0.10.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" +dependencies = [ + "bitflags 2.4.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.37", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -1572,10 +1717,12 @@ dependencies = [ "http-body", "hyper", "hyper-rustls", + "hyper-tls", "ipnet", "js-sys", "log", "mime", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -1585,6 +1732,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "tokio", + "tokio-native-tls", "tokio-rustls", "tokio-socks", "tokio-util", @@ -1659,6 +1807,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f" +dependencies = [ + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "rustls" version = "0.21.7" @@ -1696,6 +1857,15 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +[[package]] +name = "schannel" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +dependencies = [ + "windows-sys", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -1712,6 +1882,29 @@ dependencies = [ "untrusted", ] +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "1.0.19" @@ -1900,19 +2093,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" [[package]] -name = "thiserror" -version = "1.0.48" +name = "tempfile" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys", +] + +[[package]] +name = "thiserror" +version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.48" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", @@ -2003,6 +2209,16 @@ dependencies = [ "syn 2.0.37", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.24.1" @@ -2075,7 +2291,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.0.1", "serde", "serde_spanned", "toml_datetime", @@ -2172,6 +2388,12 @@ dependencies = [ "rust_hawktracer", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version-compare" version = "0.1.1" diff --git a/Cargo.toml b/Cargo.toml index 11cdfb9..3355253 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,22 +6,34 @@ version = "0.1.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +# Web Requests & Async Runtime +tokio = { version = "1.32.0", features = ["full"] } actix-web = "4.4.0" -image = "0.24.7" -libwebp-sys = { version = "0.9.4", optional = true } -mimalloc = "0.1.39" -once_cell = "1.18.0" +reqwest = { version = "0.11.20", features = ["stream", "brotli", "gzip", "socks"], default-features = false } qstring = "0.7.2" + +# Alternate Allocator +mimalloc = { version = "0.1.39", optional = true } + +# Transcoding Images to WebP/AVIF to save bandwidth +image = { version = "0.24.7", optional = true } +libwebp-sys = { version = "0.9.4", optional = true } ravif = { version = "0.11.3", optional = true } rgb = { version = "0.8.36", optional = true } + +once_cell = "1.18.0" regex = "1.9.5" -reqwest = { version = "0.11.20", features = ["rustls-tls", "stream", "brotli", "gzip", "socks"], default-features = false } -tokio = { version = "1.32.0", features = ["full"] } [features] -default = ["webp"] -avif = ["dep:ravif", "dep:rgb"] -webp = ["dep:libwebp-sys"] +default = ["webp", "mimalloc", "reqwest-rustls"] + +reqwest-rustls = ["reqwest/rustls-tls"] +reqwest-native-tls = ["reqwest/default-tls"] + +avif = ["dep:ravif", "dep:rgb", "dep:image"] +webp = ["dep:libwebp-sys", "dep:image"] + +mimalloc = ["dep:mimalloc"] [profile.release] -lto = true \ No newline at end of file +lto = true diff --git a/src/main.rs b/src/main.rs index f54a7e4..8bc6ddb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,21 @@ use actix_web::http::Method; use actix_web::{web, App, HttpRequest, HttpResponse, HttpResponseBuilder, HttpServer}; -use mimalloc::MiMalloc; use once_cell::sync::Lazy; use qstring::QString; use regex::Regex; use reqwest::{Body, Client, Request, Url}; use std::env; use std::error::Error; -use tokio::sync::oneshot; -use tokio::task::spawn_blocking; +#[cfg(not(any(feature = "reqwest-native-tls", feature = "reqwest-rustls")))] +compile_error!("feature \"reqwest-native-tls\" or \"reqwest-rustls\" must be set for proxy to have TLS support"); + +#[cfg(any(feature = "webp", feature = "avif"))] +use tokio::{sync::oneshot, task::spawn_blocking}; + +#[cfg(feature = "mimalloc")] #[global_allocator] -static GLOBAL: MiMalloc = MiMalloc; +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; #[actix_web::main] async fn main() -> std::io::Result<()> { @@ -22,8 +26,8 @@ async fn main() -> std::io::Result<()> { App::new().default_service(web::to(index)) }); // get port from env - if env::var("UDS").is_ok() { - server.bind_uds("./socket/actix.sock")? + if let Ok(unix_socket) = env::var("BIND_UNIX") { + server.bind_uds(unix_socket)? } else { let bind = env::var("BIND").unwrap_or_else(|_| "0.0.0.0:8080".to_string()); server.bind(bind)? @@ -48,17 +52,17 @@ static CLIENT: Lazy = Lazy::new(|| { None }; - let builder = if proxy.is_some() { + + let builder = if let Some(proxy) = proxy { // proxy basic auth if let Ok(proxy_auth_user) = env::var("PROXY_USER") { let proxy_auth_pass = env::var("PROXY_PASS").unwrap_or_default(); builder.proxy( proxy - .unwrap() .basic_auth(&proxy_auth_user, &proxy_auth_pass), ) } else { - builder.proxy(proxy.unwrap()) + builder.proxy(proxy) } } else { builder @@ -133,6 +137,9 @@ async fn index(req: HttpRequest) -> Result> { return Err("No host provided".into()); } + #[cfg(any(feature = "webp", feature = "avif"))] + let disallow_image_transcoding = env::var("DISALLOW_IMAGE_TRANSCODING").is_ok(); + let rewrite = query.get("rewrite") != Some("false"); #[cfg(feature = "avif")] @@ -213,7 +220,9 @@ async fn index(req: HttpRequest) -> Result> { if rewrite { if let Some(content_type) = resp.headers().get("content-type") { #[cfg(feature = "avif")] - if content_type == "image/webp" || content_type == "image/jpeg" && avif { + if disallow_image_transcoding + && (content_type == "image/webp" || content_type == "image/jpeg" && avif) + { let resp_bytes = resp.bytes().await.unwrap(); let (tx, rx) = oneshot::channel::<(Vec, &'static str)>(); spawn_blocking(|| { @@ -235,11 +244,11 @@ async fn index(req: HttpRequest) -> Result> { .with_speed(7) .encode_rgb(buffer); - return if let Ok(res) = res { + if let Ok(res) = res { tx.send((res.avif_file.to_vec(), "image/avif")).unwrap(); } else { tx.send((resp_bytes.into(), "image/jpeg")).unwrap(); - }; + } }); let (body, content_type) = rx.await.unwrap(); response.content_type(content_type); @@ -247,7 +256,7 @@ async fn index(req: HttpRequest) -> Result> { } #[cfg(feature = "webp")] - if content_type == "image/jpeg" { + if !disallow_image_transcoding && content_type == "image/jpeg" { let resp_bytes = resp.bytes().await.unwrap(); let (tx, rx) = oneshot::channel::<(Vec, &'static str)>(); spawn_blocking(|| {