From 5b6d2c6cf7f9b6ddaad3906457571af5a6d7dde6 Mon Sep 17 00:00:00 2001 From: Moritz Ruth Date: Fri, 28 Feb 2025 21:40:45 +0100 Subject: [PATCH] commit 03 --- .dockerignore | 3 + .forgejo/workflows/build.yaml | 29 ++ Cargo.lock | 565 ++++++++++++---------------------- Cargo.toml | 36 +-- Containerfile | 18 ++ rust-toolchain.toml | 3 +- src/api.rs | 16 +- src/caddy.rs | 15 +- src/config.rs | 8 +- src/main.rs | 10 +- src/sites.rs | 107 ++++--- 11 files changed, 338 insertions(+), 472 deletions(-) create mode 100644 .dockerignore create mode 100644 .forgejo/workflows/build.yaml create mode 100644 Containerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..3f350d5 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +/target +/run +/.idea \ No newline at end of file diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml new file mode 100644 index 0000000..8a6edd8 --- /dev/null +++ b/.forgejo/workflows/build.yaml @@ -0,0 +1,29 @@ +name: "Build" +on: + push: + branches: + - dev + tags: + - v** + +jobs: + build: + runs-on: "docker" + + steps: + - name: "Checkout" + uses: "https://code.forgejo.org/actions/checkout@v4" + + - name: "Login to the container registry" + uses: "https://github.com/docker/login-action@v3" + with: + registry: git.moritzruth.de + username: ${{ github.actor }} + password: ${{ github.token }} + + - name: "Build and push" + uses: "https://github.com/docker/build-push-action" + with: + file: "Containerfile" + push: true + tags: "git.moritzruth.de/moritzruth/sscdc:${{ github.ref_name }}" \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 82390f0..cc5d7aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -178,6 +178,16 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "async-attributes" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "async-channel" version = "1.9.0" @@ -237,7 +247,6 @@ dependencies = [ "blocking", "futures-lite 2.6.0", "once_cell", - "tokio 1.43.0", ] [[package]] @@ -316,18 +325,6 @@ dependencies = [ "pin-project-lite 0.2.16", ] -[[package]] -name = "async-native-tls" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e9e7a929bd34c68a82d58a4de7f86fffdaf97fb2af850162a7bb19dd7269b33" -dependencies = [ - "async-std", - "native-tls", - "thiserror 1.0.69", - "url", -] - [[package]] name = "async-process" version = "2.3.0" @@ -349,20 +346,20 @@ dependencies = [ [[package]] name = "async-session" -version = "2.0.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345022a2eed092cd105cc1b26fd61c341e100bd5fcbbd792df4baf31c2cc631f" +checksum = "07da4ce523b4e2ebaaf330746761df23a465b951a83d84bbce4233dabedae630" dependencies = [ "anyhow", - "async-std", + "async-lock 2.8.0", "async-trait", - "base64 0.12.3", + "base64 0.13.1", "bincode", "blake3", "chrono", - "hmac 0.8.1", - "kv-log-macro", - "rand 0.7.3", + "hmac 0.11.0", + "log", + "rand 0.8.5", "serde", "serde_json", "sha2", @@ -406,6 +403,7 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" dependencies = [ + "async-attributes", "async-channel 1.9.0", "async-global-executor", "async-io 2.4.0", @@ -486,12 +484,6 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" -[[package]] -name = "base64" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" - [[package]] name = "base64" version = "0.13.1" @@ -580,12 +572,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" -[[package]] -name = "bytes" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" - [[package]] name = "bytes" version = "1.10.0" @@ -619,6 +605,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.40" @@ -627,10 +619,8 @@ checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" dependencies = [ "android-tzdata", "iana-time-zone", - "js-sys", "num-traits", "serde", - "wasm-bindgen", "windows-link", ] @@ -725,16 +715,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -800,6 +780,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "crypto-mac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "ctr" version = "0.6.0" @@ -868,7 +858,7 @@ dependencies = [ "crossbeam-queue", "num_cpus", "serde", - "tokio 1.43.0", + "tokio", ] [[package]] @@ -908,15 +898,6 @@ dependencies = [ "syn 2.0.98", ] -[[package]] -name = "encoding_rs" -version = "0.8.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" -dependencies = [ - "cfg-if 1.0.0", -] - [[package]] name = "env_filter" version = "0.1.3" @@ -1063,21 +1044,6 @@ 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.1" @@ -1232,20 +1198,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if 1.0.0", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets 0.52.6", + "wasm-bindgen", ] [[package]] @@ -1276,25 +1232,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "h2" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" -dependencies = [ - "atomic-waker", - "bytes 1.10.0", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap", - "slab", - "tokio 1.43.0", - "tokio-util", - "tracing", -] - [[package]] name = "hashbrown" version = "0.14.5" @@ -1329,16 +1266,6 @@ dependencies = [ "hmac 0.10.1", ] -[[package]] -name = "hmac" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" -dependencies = [ - "crypto-mac 0.8.0", - "digest", -] - [[package]] name = "hmac" version = "0.10.1" @@ -1349,13 +1276,23 @@ dependencies = [ "digest", ] +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac 0.11.0", + "digest", +] + [[package]] name = "http" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ - "bytes 1.10.0", + "bytes", "fnv", "itoa", ] @@ -1366,7 +1303,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ - "bytes 1.10.0", + "bytes", "http", ] @@ -1376,7 +1313,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ - "bytes 1.10.0", + "bytes", "futures-util", "http", "http-body", @@ -1390,7 +1327,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1947510dc91e2bf586ea5ffb412caad7673264e14bb39fb9078da114a94ce1a5" dependencies = [ "async-h1", - "async-native-tls", "async-std", "async-trait", "cfg-if 1.0.0", @@ -1399,7 +1335,6 @@ dependencies = [ "futures", "http-types", "log", - "tokio 0.2.25", ] [[package]] @@ -1442,17 +1377,16 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ - "bytes 1.10.0", + "bytes", "futures-channel", "futures-util", - "h2", "http", "http-body", "httparse", "itoa", "pin-project-lite 0.2.16", "smallvec", - "tokio 1.43.0", + "tokio", "want", ] @@ -1468,25 +1402,10 @@ dependencies = [ "hyper-util", "rustls", "rustls-pki-types", - "tokio 1.43.0", + "tokio", "tokio-rustls", "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes 1.10.0", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio 1.43.0", - "tokio-native-tls", - "tower-service", + "webpki-roots", ] [[package]] @@ -1495,7 +1414,7 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ - "bytes 1.10.0", + "bytes", "futures-channel", "futures-util", "http", @@ -1503,7 +1422,7 @@ dependencies = [ "hyper", "pin-project-lite 0.2.16", "socket2 0.5.8", - "tokio 1.43.0", + "tokio", "tower-service", "tracing", ] @@ -1865,23 +1784,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nom" version = "5.1.3" @@ -1933,50 +1835,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" -[[package]] -name = "openssl" -version = "0.10.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" -dependencies = [ - "bitflags 2.8.0", - "cfg-if 1.0.0", - "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.98", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-sys" -version = "0.9.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "owo-colors" version = "3.5.0" @@ -2057,12 +1915,6 @@ dependencies = [ "futures-io", ] -[[package]] -name = "pkg-config" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" - [[package]] name = "polling" version = "2.8.0" @@ -2151,6 +2003,58 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quinn" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" +dependencies = [ + "bytes", + "pin-project-lite 0.2.16", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2 0.5.8", + "thiserror 2.0.11", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" +dependencies = [ + "bytes", + "getrandom 0.2.15", + "rand 0.8.5", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.11", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.5.8", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "quote" version = "1.0.38" @@ -2276,42 +2180,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" dependencies = [ "base64 0.22.1", - "bytes 1.10.0", - "encoding_rs", + "bytes", + "futures-channel", "futures-core", "futures-util", - "h2", "http", "http-body", "http-body-util", "hyper", "hyper-rustls", - "hyper-tls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite 0.2.16", + "quinn", + "rustls", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", - "system-configuration", - "tokio 1.43.0", - "tokio-native-tls", - "tokio-util", + "tokio", + "tokio-rustls", "tower", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", "web-sys", + "webpki-roots", "windows-registry", ] @@ -2330,10 +2232,14 @@ dependencies = [ ] [[package]] -name = "route-recognizer" -version = "0.2.0" +name = "routefinder" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56770675ebc04927ded3e60633437841581c285dc6236109ea25fbf3beb7b59e" +checksum = "a44ef95cc607e41a7021da5cfb0f357ee0805113af2e9e6c617857c260940db4" +dependencies = [ + "smartcow", + "smartstring", +] [[package]] name = "rustc-demangle" @@ -2341,6 +2247,12 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustc_version" version = "0.2.3" @@ -2384,6 +2296,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" dependencies = [ "once_cell", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -2404,6 +2317,9 @@ name = "rustls-pki-types" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +dependencies = [ + "web-time", +] [[package]] name = "rustls-webpki" @@ -2428,44 +2344,12 @@ version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" -[[package]] -name = "schannel" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" -dependencies = [ - "windows-sys 0.59.0", -] - [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.8.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.9.0" @@ -2637,6 +2521,24 @@ version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +[[package]] +name = "smartcow" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e3ed3ccf93c7425507e5e2261a3fc90d14267d491f360b9b679ae0a4ce693e" +dependencies = [ + "smartstring", +] + +[[package]] +name = "smartstring" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e714dff2b33f2321fdcd475b71cec79781a692d846f37f415fb395a1d2bcd48e" +dependencies = [ + "static_assertions", +] + [[package]] name = "socket2" version = "0.4.10" @@ -2667,7 +2569,6 @@ dependencies = [ "color-eyre", "env_logger", "figment", - "futures", "http-client", "log", "once_cell", @@ -2677,7 +2578,6 @@ dependencies = [ "serde_json", "serde_regex", "tide", - "tokio 1.43.0", "toml", "validator", "zip", @@ -2885,41 +2785,6 @@ dependencies = [ "syn 2.0.98", ] -[[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" -dependencies = [ - "bitflags 2.8.0", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tempfile" -version = "3.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230" -dependencies = [ - "cfg-if 1.0.0", - "fastrand 2.3.0", - "getrandom 0.3.1", - "once_cell", - "rustix 0.38.44", - "windows-sys 0.59.0", -] - [[package]] name = "thiserror" version = "1.0.69" @@ -2972,9 +2837,9 @@ dependencies = [ [[package]] name = "tide" -version = "0.16.0" +version = "0.17.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c459573f0dd2cc734b539047f57489ea875af8ee950860ded20cf93a79a1dee0" +checksum = "c5a885fbeb66af9d607a731ce167e3fdfe65e49a68f37f4bbd8618b5efc6ad51" dependencies = [ "async-h1", "async-session", @@ -2988,7 +2853,7 @@ dependencies = [ "kv-log-macro", "log", "pin-project-lite 0.2.16", - "route-recognizer", + "routefinder", "serde", "serde_json", ] @@ -3042,16 +2907,20 @@ dependencies = [ ] [[package]] -name = "tokio" -version = "0.2.25" +name = "tinyvec" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" dependencies = [ - "bytes 0.5.6", - "pin-project-lite 0.1.12", - "slab", + "tinyvec_macros", ] +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.43.0" @@ -3059,37 +2928,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", - "bytes 1.10.0", + "bytes", "libc", "mio", "pin-project-lite 0.2.16", - "signal-hook-registry", "socket2 0.5.8", - "tokio-macros", "windows-sys 0.52.0", ] -[[package]] -name = "tokio-macros" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - -[[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 1.43.0", -] - [[package]] name = "tokio-rustls" version = "0.26.1" @@ -3097,20 +2943,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ "rustls", - "tokio 1.43.0", -] - -[[package]] -name = "tokio-util" -version = "0.7.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" -dependencies = [ - "bytes 1.10.0", - "futures-core", - "futures-sink", - "pin-project-lite 0.2.16", - "tokio 1.43.0", + "tokio", ] [[package]] @@ -3157,7 +2990,7 @@ dependencies = [ "futures-util", "pin-project-lite 0.2.16", "sync_wrapper", - "tokio 1.43.0", + "tokio", "tower-layer", "tower-service", ] @@ -3296,9 +3129,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "validator" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0b4a29d8709210980a09379f27ee31549b73292c87ab9899beee1c0d3be6303" +checksum = "43fb22e1a008ece370ce08a3e9e4447a910e92621bb49b85d6e48a45397e7cfa" dependencies = [ "idna", "once_cell", @@ -3312,9 +3145,9 @@ dependencies = [ [[package]] name = "validator_derive" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac855a2ce6f843beb229757e6e570a42e837bcb15e5f449dd48d5747d41bf77" +checksum = "b7df16e474ef958526d1205f6dda359fdfab79d9aa6d54bafcb92dcd07673dca" dependencies = [ "darling", "once_cell", @@ -3366,12 +3199,6 @@ dependencies = [ "sval_serde", ] -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.5" @@ -3405,15 +3232,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasi" -version = "0.13.3+wasi-0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" -dependencies = [ - "wit-bindgen-rt", -] - [[package]] name = "wasm-bindgen" version = "0.2.100" @@ -3487,19 +3305,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-streams" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "web-sys" version = "0.3.77" @@ -3510,6 +3315,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.26.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "winapi" version = "0.3.9" @@ -3734,15 +3558,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "wit-bindgen-rt" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" -dependencies = [ - "bitflags 2.8.0", -] - [[package]] name = "write16" version = "1.0.0" diff --git a/Cargo.toml b/Cargo.toml index 01bd145..077692a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,23 +4,21 @@ version = "0.1.0" edition = "2024" [dependencies] -reqwest = { version = "0.12.12", features = ["json", "stream"] } -toml = "0.8.19" -serde = "1.0.217" -validator = { version = "0.19.0", features = ["derive"] } -figment = { version = "0.10.19", features = ["toml"] } -color-eyre = "0.6.3" -serde_regex = "1.1.0" -regex = "1.11.1" -tokio = { version = "1.43.0", default-features = false, features = ["macros", "process", "fs", "rt"] } -log = "0.4.26" -env_logger = "0.11.6" -serde_json = "1.0.139" -camino = "1.1.9" -tide = { version = "0.16.0"} -zip = { version = "2.2.3", default-features = false, features = ["deflate"] } -futures = "0.3.31" -async-std = { version = "1.13.0", features = ["tokio1"] } async-h1 = "2.3.4" -http-client = { version = "6.5.3", features = ["async-h1", "tokio"] } -once_cell = "1.20.3" \ No newline at end of file +async-std = { version = "1.13.0", features = ["attributes"] } +camino = "1.1.9" +color-eyre = "0.6.3" +env_logger = "0.11.6" +figment = { version = "0.10.19", features = ["toml"] } +http-client = { version = "6.5.3", default-features = false, features = ["async-h1", "async-std", "h1_client"] } +log = "0.4.26" +once_cell = "1.20.3" +regex = "1.11.1" +reqwest = { version = "0.12.12", default-features = false, features = ["blocking", "rustls-tls"] } +serde = "1.0.217" +serde_json = "1.0.139" +serde_regex = "1.1.0" +tide = "0.17.0-beta.1" +toml = "0.8.19" +validator = { version = "0.20.0", features = ["derive"] } +zip = { version = "2.2.3", default-features = false, features = ["deflate"] } \ No newline at end of file diff --git a/Containerfile b/Containerfile new file mode 100644 index 0000000..855fffd --- /dev/null +++ b/Containerfile @@ -0,0 +1,18 @@ +FROM docker.io/rustlang/rust:nightly-alpine AS app-builder +WORKDIR /app +COPY . /app +RUN apk add musl-dev +RUN CADDY_PATH=/caddy cargo build --release + +FROM docker.io/caddy:builder-alpine AS caddy-builder +RUN xcaddy build + +FROM gcr.io/distroless/static-debian12 +COPY --from=app-builder /app/target/release/sscdc / +COPY --from=caddy-builder /usr/bin/caddy /caddy + +VOLUME "/config.toml" +VOLUME "/sites" +EXPOSE 80 + +CMD ["./sscdc"] \ No newline at end of file diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 271800c..108eb52 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,3 @@ [toolchain] -channel = "nightly" \ No newline at end of file +channel = "nightly" +targets = ["x86_64-unknown-linux-musl"] \ No newline at end of file diff --git a/src/api.rs b/src/api.rs index c0c375e..5dae5ff 100644 --- a/src/api.rs +++ b/src/api.rs @@ -2,14 +2,11 @@ use crate::config::Config; use crate::sites::SitesWorker; use camino::Utf8Path; use color_eyre::eyre::{WrapErr, eyre}; -use log::error; use serde::Deserialize; -use std::str::pattern::Pattern; use std::sync::Arc; -use tide::http::headers::HeaderName; +use async_std::{fs, task}; +use async_std::task::JoinHandle; use tide::{Request, StatusCode}; -use tokio::fs; -use tokio::task::JoinHandle; #[derive(Clone)] struct State { @@ -35,9 +32,9 @@ pub async fn start_api_server( server.at("/version").get(|_| async { Ok(env!("CARGO_PKG_VERSION")) }); let path = api_socket_path.to_path_buf().into_std_path_buf(); - fs::remove_file(&path).await?; + let _ = fs::remove_file(&path).await; - Ok(tokio::spawn(async { + Ok(task::spawn(async { server.listen(path).await.wrap_err("IO error in API server")?; Err(eyre!("The API unexpectedly stopped without error.")) })) @@ -68,6 +65,9 @@ async fn handle_notify(mut request: Request) -> tide::Result { Ok(StatusCode::NoContent.into()) } else { - Err(tide::Error::from_str(StatusCode::Unauthorized, "The provided secret is not valid for this domain.")) + Err(tide::Error::from_str( + StatusCode::Unauthorized, + "The provided secret is not valid for this domain.", + )) } } diff --git a/src/caddy.rs b/src/caddy.rs index f027451..916d30f 100644 --- a/src/caddy.rs +++ b/src/caddy.rs @@ -8,9 +8,9 @@ use log::debug; use serde_json::json; use std::process::Stdio; use std::str::FromStr; -use tokio::io::AsyncWriteExt; -use tokio::process::Command; -use tokio::time; +use std::time::Duration; +use async_std::io::WriteExt; +use async_std::process::Command; pub struct CaddyController { api_socket_path: Utf8PathBuf, @@ -156,8 +156,11 @@ pub async fn start_caddy(api_socket_path: &Utf8Path, sockets_directory_path: &Ut // Stop not properly cleaned up proxy. let _ = request_uds(&caddy_admin_socket_path, Request::new(Method::Post, "http://localhost/stop")).await; + let caddy_path = option_env!("CADDY_PATH").unwrap_or("caddy"); + debug!("Caddy path: {}", caddy_path); + // Spawn a new proxy. - let process = Command::new("caddy").args(&["run", "--config", "-"]).stdin(Stdio::piped()).spawn()?; + let process = Command::new(caddy_path).args(&["run", "--config", "-"]).stdin(Stdio::piped()).spawn()?; let initial_configuration_object = get_initial_caddy_configuration_object(&caddy_admin_socket_path, api_socket_path); let initial_configuration_string = initial_configuration_object.to_string(); @@ -165,11 +168,11 @@ pub async fn start_caddy(api_socket_path: &Utf8Path, sockets_directory_path: &Ut process .stdin - .ok_or_eyre("The caddy process stdin is not open.")? + .ok_or_eyre("The Caddy process STDIN is not open.")? .write_all(initial_configuration_string.as_ref()) .await?; - time::sleep(time::Duration::from_secs(1)).await; + async_std::task::sleep(Duration::from_secs(1)).await; Ok(CaddyController { api_socket_path: api_socket_path.to_path_buf(), diff --git a/src/config.rs b/src/config.rs index 57159cf..e915061 100644 --- a/src/config.rs +++ b/src/config.rs @@ -3,6 +3,7 @@ use figment::providers::{Format, Toml}; use figment::Figment; use serde::Deserialize; use std::collections::HashMap; +use async_std::task; use color_eyre::eyre::WrapErr; use once_cell::sync::Lazy; use regex::Regex; @@ -10,7 +11,6 @@ use validator::Validate; #[derive(Deserialize, Debug, Validate)] pub struct Config { - pub port: u16, pub sites_directory: String, pub sockets_directory: String, #[validate(nested)] @@ -27,11 +27,11 @@ pub struct ConfigScope { pub secret: String } -pub fn load_config() -> Result { - let config: Config = Figment::new() +pub async fn load_config() -> Result { + let config: Config = task::spawn_blocking(|| Figment::new() .merge(Toml::file("./config.toml")) .extract() - .wrap_err("Failed to load the configuration.")?; + .wrap_err("Failed to load the configuration.")).await?; config.validate().wrap_err("Failed to validate the configuration.")?; Ok(config) diff --git a/src/main.rs b/src/main.rs index 6fd52e0..655897e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,24 +10,24 @@ use camino::Utf8Path; use color_eyre::Result; use color_eyre::eyre::WrapErr; use log::LevelFilter; -use std::fs; use std::sync::Arc; +use async_std::fs; mod api; mod caddy; mod config; mod sites; -#[tokio::main(flavor = "current_thread")] +#[async_std::main] async fn main() -> Result<()> { color_eyre::install()?; env_logger::Builder::new().filter_module("sscdc", LevelFilter::Info).parse_default_env().init(); log::info!("Loading configuration…"); - let config = load_config()?; + let config = load_config().await?; let sockets_directory_path = Utf8Path::new(&config.sockets_directory); - fs::create_dir_all(&sockets_directory_path).wrap_err("Failed to access or create the sockets directory.")?; + fs::create_dir_all(sockets_directory_path.as_std_path()).await.wrap_err("Failed to access or create the sockets directory.")?; let sockets_directory_path = sockets_directory_path.canonicalize_utf8().unwrap(); let api_socket_path = sockets_directory_path.join("api.sock"); @@ -41,5 +41,5 @@ async fn main() -> Result<()> { log::debug!("The internal API server is listening at {api_socket_path}"); log::info!("Startup complete."); - sites_worker_join_handle.await??; + sites_worker_join_handle.await?; } diff --git a/src/sites.rs b/src/sites.rs index 2363b29..dcc9b13 100644 --- a/src/sites.rs +++ b/src/sites.rs @@ -1,19 +1,18 @@ use crate::caddy::CaddyController; +use async_std::io::{BufReader, BufWriter, WriteExt}; +use async_std::net::TcpStream; +use async_std::stream::StreamExt; +use async_std::sync::RwLock; +use async_std::{fs, task}; use camino::{Utf8Path, Utf8PathBuf}; use color_eyre::Result; -use color_eyre::eyre::{eyre, WrapErr}; -use futures::StreamExt; +use color_eyre::eyre::{WrapErr, eyre}; use log::{debug, info}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; -use std::sync::{Arc, RwLockReadGuard, RwLockWriteGuard}; +use std::sync::Arc; use std::time::Duration; -use tide::http::bail; -use tokio::fs; -use tokio::io::{AsyncWriteExt, BufWriter}; -use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender}; -use tokio::sync::{RwLock}; -use tokio::task::JoinHandle; +use async_std::task::JoinHandle; #[derive(Serialize, Deserialize)] pub struct SiteState { @@ -23,13 +22,13 @@ pub struct SiteState { impl SiteState { async fn read_from_site_directory(site_directory_path: &Utf8Path) -> Result { - let string = fs::read_to_string(site_directory_path.join("site.toml")).await?; + let string = fs::read_to_string(site_directory_path.join("site.toml").into_std_path_buf()).await?; Ok(toml::from_str::(&string)?) } async fn write_to_site_directory(&self, site_directory_path: &Utf8Path) -> Result<()> { - fs::create_dir_all(site_directory_path).await?; - let mut file = fs::File::create(site_directory_path.join("site.toml")).await?; + fs::create_dir_all(site_directory_path.as_std_path()).await?; + let mut file = fs::File::create(site_directory_path.join("site.toml").into_std_path_buf()).await?; file.write_all(toml::to_string(&self).unwrap().as_bytes()).await?; Ok(()) } @@ -41,7 +40,7 @@ impl SiteState { return Some(current_version); } } else { - return Some(current_version) + return Some(current_version); } } @@ -66,7 +65,7 @@ type Sites = RwLock>>; pub struct SitesWorker { sites: Arc, sites_directory_path: Utf8PathBuf, - download_tasks_sender: UnboundedSender, + download_tasks_sender: async_std::channel::Sender, } impl SitesWorker { @@ -86,7 +85,7 @@ impl SitesWorker { let mut state = site.state.write().await; state.current_version = Some(SiteStateVersion { id, download_url }); state.write_to_site_directory(&site.path).await?; - self.download_tasks_sender.send(domain).unwrap(); + self.download_tasks_sender.send(domain).await?; Ok(()) } @@ -95,12 +94,13 @@ impl SitesWorker { pub async fn load_sites(sites_directory_path: &Utf8Path) -> Result { let mut sites: HashMap> = HashMap::new(); - if fs::try_exists(&sites_directory_path).await.unwrap_or(false) { - let mut dir = fs::read_dir(&sites_directory_path).await?; + if fs::metadata(sites_directory_path.as_std_path()).await.map(|m| m.is_dir()).unwrap_or(false) { + let mut dir = fs::read_dir(sites_directory_path.as_std_path()).await?; loop { - if let Some(entry) = dir.next_entry().await? { + if let Some(entry) = dir.next().await { + let entry = entry?; if entry.file_type().await?.is_dir() { - let path = Utf8PathBuf::from_path_buf(entry.path()).unwrap(); + let path = Utf8PathBuf::from_path_buf(entry.path().into()).unwrap(); let domain = path.file_name().unwrap().to_string(); let state = SiteState::read_from_site_directory(&path).await?; @@ -118,7 +118,7 @@ pub async fn load_sites(sites_directory_path: &Utf8Path) -> Result { } } } else { - fs::create_dir_all(&sites_directory_path) + fs::create_dir_all(sites_directory_path.as_std_path()) .await .wrap_err("Failed to create the sites directory (and its parents)")?; } @@ -151,47 +151,46 @@ async fn handle_download(reqwest_client: &mut reqwest::Client, sites: &Sites, ca // Download let archive_file_path = site.path.join(format!("{}.zip", current_version.id)); - let mut archive_file = fs::OpenOptions::new() + let mut archive_file_for_writing = fs::OpenOptions::new() .truncate(true) .create(true) .write(true) - .read(true) - .open(&archive_file_path).await?; - - let mut file_writer = BufWriter::new(&mut archive_file); + .open(archive_file_path.as_std_path()) + .await?; + + let mut file_writer = BufWriter::new(&mut archive_file_for_writing); let mut response = reqwest_client.get(¤t_version.download_url).send().await?; let status = response.status(); if !status.is_success() { - return Err(eyre!("Download request failed with status code {status}")) + return Err(eyre!("Download request failed with status code {status}")); } while let Some(chunk) = response.chunk().await? { file_writer.write_all(&chunk).await?; } - + file_writer.flush().await?; let extraction_directory_path = site.path.join(¤t_version.id); - let _ = fs::remove_dir_all(&extraction_directory_path).await; - fs::create_dir_all(&extraction_directory_path).await?; - + let _ = fs::remove_dir_all(extraction_directory_path.as_std_path()).await; + fs::create_dir_all(extraction_directory_path.as_std_path()).await?; + debug!("Finished download for {domain} ({}), now unpacking…", current_version.id); - + // Unpack to temp dir - tokio::task::spawn_blocking({ - let archive_file = archive_file.into_std().await; + task::spawn_blocking({ let extraction_directory_path = extraction_directory_path.clone(); + let archive_file_path = archive_file_path.clone().into_std_path_buf(); move || -> Result<()> { - let mut archive = zip::ZipArchive::new(archive_file)?; + let mut archive = zip::ZipArchive::new(std::io::BufReader::new(std::fs::File::open(archive_file_path)?))?; archive.extract(&extraction_directory_path)?; - Ok(()) } }) - .await??; - + .await?; + // Update and write state let current_version = current_version.clone(); let old_active_version = state.active_version.replace(current_version); @@ -200,33 +199,33 @@ async fn handle_download(reqwest_client: &mut reqwest::Client, sites: &Sites, ca // Update Caddy configuration info!("Download for {domain} successful, now updating proxy configuration…"); caddy_controller.upsert_site_configuration(&domain, &extraction_directory_path).await?; - + // Cleanup - fs::remove_file(archive_file_path).await?; + fs::remove_file(archive_file_path.as_std_path()).await?; if let Some(old_active_version) = old_active_version { - fs::remove_dir_all(site.path.join(old_active_version.id)).await?; + fs::remove_dir_all(site.path.join(old_active_version.id).into_std_path_buf()).await?; } - + info!("Cleanup finished for {domain}"); - + Ok(()) } -async fn sites_worker(mut download_tasks_receiver: UnboundedReceiver, sites: Arc, mut caddy_controller: CaddyController) -> Result { - let mut client = reqwest::Client::builder() - .read_timeout(Duration::from_secs(60)) +async fn sites_worker(mut download_tasks_receiver: async_std::channel::Receiver, sites: Arc, mut caddy_controller: CaddyController) -> Result { + let mut reqwest_client = reqwest::Client::builder() + .read_timeout(Duration::from_mins(1)) .timeout(Duration::from_hours(1)) .build()?; - + loop { let domain = download_tasks_receiver.recv().await.unwrap(); - handle_download(&mut client, &sites, &mut caddy_controller, domain).await?; + handle_download(&mut reqwest_client, &sites, &mut caddy_controller, domain).await?; } } pub async fn start_sites_worker(sites_directory_path: Utf8PathBuf, mut caddy_controller: CaddyController) -> Result<(SitesWorker, JoinHandle>)> { - let (download_tasks_sender, download_tasks_receiver) = tokio::sync::mpsc::unbounded_channel(); - + let (download_tasks_sender, download_tasks_receiver) = async_std::channel::unbounded(); + info!("Discovering managed sites…"); let sites = Arc::new(load_sites(&sites_directory_path).await?); let mut total_count = 0; @@ -234,11 +233,11 @@ pub async fn start_sites_worker(sites_directory_path: Utf8PathBuf, mut caddy_con for (_, site) in sites.read().await.iter() { let state = site.state.read().await; - + if let Some(current_version) = &state.current_version { let mut is_outdated = true; total_count += 1; - + if let Some(active_version) = &state.active_version { is_outdated = current_version.id != active_version.id; @@ -246,17 +245,17 @@ pub async fn start_sites_worker(sites_directory_path: Utf8PathBuf, mut caddy_con .upsert_site_configuration(&site.domain, &site.path.join(&active_version.id)) .await?; } - + if is_outdated { outdated_count += 1; - download_tasks_sender.send(site.domain.clone()).unwrap() + download_tasks_sender.send(site.domain.clone()).await?; } } } info!("Discovered {total_count} site(s), {outdated_count} outdated."); - let join_handle = tokio::spawn(sites_worker(download_tasks_receiver, Arc::clone(&sites), caddy_controller)); + let join_handle = task::spawn(sites_worker(download_tasks_receiver, Arc::clone(&sites), caddy_controller)); Ok(( SitesWorker {