From 2a5b1c0c91f2a722a8fc8c0a922a78372a0d1210 Mon Sep 17 00:00:00 2001 From: Asfmq <2696428814@qq.com> Date: Fri, 12 Jun 2026 11:15:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=9B=86=E6=88=90=20Obscura=20?= =?UTF-8?q?=E8=BF=9B=E7=A8=8B=E5=86=85=E6=97=A0=E5=A4=B4=E6=B5=8F=E8=A7=88?= =?UTF-8?q?=E5=99=A8=E3=80=81=E6=9E=81=E8=87=B4=E7=BC=96=E8=AF=91=E7=98=A6?= =?UTF-8?q?=E8=BA=AB=20profile=20=E4=B8=8E=E8=AF=8D=E5=85=B8=E5=86=85?= =?UTF-8?q?=E5=AD=98=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 下载器 Obscura 后备通道拆分为条件编译双路径: 进程内模式 (obscura-inprocess feature) 通过 spawn_blocking + 单线程 runtime 驱动 V8 直接抓取;默认外部命令行模式通过 bin/obscura 子进程调用 - Cargo.toml 新增 obscura-browser/obscura-net 可选依赖与 release-min profile (LTO + strip + opt-level="s",二进制 17→8.3 MB,VSZ 1.27G→302M) - 词典加载后 shrink_to_fit() 释放预留容量,降低常驻内存 - README 与 deployment.md 扩写 Obscura 双模式部署及低配服务器优化指南 - 新增 Obscura mock 集成测试,补齐测试 fixture 字段 --- Cargo.lock | 1036 ++++++++++++++++++++++++++++++++++- Cargo.toml | 14 + README.md | 19 +- docs/deployment.md | 91 ++- libs/obscura | 1 + src/api/helpers.rs | 2 + src/services/download.rs | 148 ++++- src/services/translation.rs | 1 + 8 files changed, 1283 insertions(+), 29 deletions(-) create mode 160000 libs/obscura diff --git a/Cargo.lock b/Cargo.lock index c467bd3..037ca6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,6 +41,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 = "allocator-api2" version = "0.2.21" @@ -75,8 +90,10 @@ dependencies = [ "futures-util", "hmac 0.12.1", "html2md", + "obscura-browser", + "obscura-net", "quick-xml", - "rand", + "rand 0.8.6", "regex", "reqwest", "serde", @@ -95,6 +112,18 @@ dependencies = [ "zip", ] +[[package]] +name = "async-compression" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79b3f8a79cccc2898f31920fc69f304859b3bd567490f75ebf51ae1c792a9ac" +dependencies = [ + "compression-codecs", + "compression-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "async-trait" version = "0.1.89" @@ -195,6 +224,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "az" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be5eb007b7cacc6c660343e96f650fedf4b5a77512399eb952ca6642cf8d13f7" + [[package]] name = "base64" version = "0.21.7" @@ -207,12 +242,66 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref", + "vsimd", +] + [[package]] name = "base64ct" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bindgen" +version = "0.71.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex 1.3.0", + "syn 2.0.117", +] + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "bitflags" version = "2.13.0" @@ -222,6 +311,18 @@ dependencies = [ "serde_core", ] +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -241,6 +342,27 @@ dependencies = [ "zeroize", ] +[[package]] +name = "brotli" +version = "8.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8119e4516436f5708bbc474a9d395bf12f1b5395e93a92a56e647ac3388c8610" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5962523e1b92ce1b5e793d9169b9943eece10d39f62550bc04bb605d75b94924" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + [[package]] name = "bumpalo" version = "3.20.3" @@ -268,6 +390,26 @@ dependencies = [ "libbz2-rs-sys", ] +[[package]] +name = "capacity_builder" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f2d24a6dcf0cd402a21b65d35340f3a49ff3475dc5fdac91d22d2733e6641c6" +dependencies = [ + "capacity_builder_macros", + "itoa", +] + +[[package]] +name = "capacity_builder_macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b4a6cae9efc04cc6cbb8faf338d2c497c165c83e74509cf4dbedea948bbf6e5" +dependencies = [ + "quote", + "syn 2.0.117", +] + [[package]] name = "cc" version = "1.2.63" @@ -277,7 +419,7 @@ dependencies = [ "find-msvc-tools", "jobserver", "libc", - "shlex", + "shlex 2.0.1", ] [[package]] @@ -286,12 +428,27 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[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.45" @@ -316,6 +473,17 @@ dependencies = [ "inout", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "cmov" version = "0.5.4" @@ -332,6 +500,24 @@ dependencies = [ "memchr", ] +[[package]] +name = "compression-codecs" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce2548391e9c1929c21bf6aa2680af86fe4c1b33e6cea9ac1cfeec0bd11218cf" +dependencies = [ + "brotli", + "compression-core", + "flate2", + "memchr", +] + +[[package]] +name = "compression-core" +version = "0.4.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc14f565cf027a105f7a44ccf9e5b424348421a1d8952a8fc9d499d313107789" + [[package]] name = "const-oid" version = "0.9.6" @@ -350,6 +536,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" +[[package]] +name = "cooked-waker" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147be55d677052dabc6b22252d5dd0fd4c29c8c27aa4f2fbef0f94aa003b406f" + [[package]] name = "cookie" version = "0.18.1" @@ -496,6 +688,29 @@ dependencies = [ "hybrid-array", ] +[[package]] +name = "cssparser" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c66d1cd8ed61bf80b38432613a7a2f09401ab8d0501110655f8b341484a3e3" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.117", +] + [[package]] name = "ctutils" version = "0.4.2" @@ -505,12 +720,138 @@ dependencies = [ "cmov", ] +[[package]] +name = "data-encoding" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" + +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "serde", + "uuid", +] + [[package]] name = "deflate64" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac6b926516df9c60bfa16e107b21086399f8285a44ca9711344b9e553c5146e2" +[[package]] +name = "deno_core" +version = "0.350.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e273b731fce500130790e777cb2631dc451db412975304d23816c1e444a10c5b" +dependencies = [ + "anyhow", + "az", + "bincode", + "bit-set", + "bit-vec", + "bytes", + "capacity_builder", + "cooked-waker", + "deno_core_icudata", + "deno_error", + "deno_ops", + "deno_path_util", + "deno_unsync", + "futures", + "indexmap", + "libc", + "parking_lot", + "percent-encoding", + "pin-project", + "serde", + "serde_json", + "serde_v8", + "smallvec", + "sourcemap", + "static_assertions", + "thiserror 2.0.18", + "tokio", + "url", + "v8", + "wasm_dep_analyzer", +] + +[[package]] +name = "deno_core_icudata" +version = "0.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4dccb6147bb3f3ba0c7a48e993bfeb999d2c2e47a81badee80e2b370c8d695" + +[[package]] +name = "deno_error" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612ec3fc481fea759141b0c57810889b0a4fb6fee8f10748677bfe492fd30486" +dependencies = [ + "deno_error_macro", + "libc", + "serde", + "serde_json", + "tokio", + "url", +] + +[[package]] +name = "deno_error_macro" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8380a4224d5d2c3f84da4d764c4326cac62e9a1e3d4960442d29136fc07be863" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "deno_ops" +version = "0.226.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28b12489187c71fa123731cc783d48beb17ae5df04da991909cc2ae5a3d0ef9" +dependencies = [ + "indexmap", + "proc-macro-rules", + "proc-macro2", + "quote", + "stringcase", + "strum", + "strum_macros", + "syn 2.0.117", + "thiserror 2.0.18", +] + +[[package]] +name = "deno_path_util" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516f813389095889776b81cc9108ff6f336fd9409b4b12fc0138aea23d2708e1" +dependencies = [ + "deno_error", + "percent-encoding", + "sys_traits", + "thiserror 2.0.18", + "url", +] + +[[package]] +name = "deno_unsync" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6742a724e8becb372a74c650a1aefb8924a5b8107f7d75b3848763ea24b27a87" +dependencies = [ + "futures-util", + "parking_lot", + "tokio", +] + [[package]] name = "der" version = "0.7.10" @@ -531,6 +872,17 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derive_more" +version = "0.99.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "digest" version = "0.10.7" @@ -582,6 +934,21 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "dtoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + [[package]] name = "either" version = "1.16.0" @@ -703,6 +1070,22 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fslock" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04412b8935272e3a9bae6f48c7bfff74c2911f60525404edfdd28e49884c3bfb" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futf" version = "0.1.5" @@ -713,6 +1096,21 @@ dependencies = [ "new_debug_unreachable", ] +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.32" @@ -786,6 +1184,7 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -796,6 +1195,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -813,8 +1221,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -824,9 +1234,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi 5.3.0", "wasip2", + "wasm-bindgen", ] [[package]] @@ -844,6 +1256,21 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "gzip-header" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86848f4fd157d91041a62c78046fb7b248bcc2dce78376d436a1756e9a038577" +dependencies = [ + "crc32fast", +] + [[package]] name = "h2" version = "0.4.14" @@ -960,7 +1387,7 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cff9891f2e0d9048927fbdfc28b11bf378f6a93c7ba70b23d0fbee9af6071b4" dependencies = [ - "html5ever", + "html5ever 0.27.0", "jni", "lazy_static", "markup5ever_rcdom", @@ -976,12 +1403,24 @@ checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" dependencies = [ "log", "mac", - "markup5ever", + "markup5ever 0.12.1", "proc-macro2", "quote", "syn 2.0.117", ] +[[package]] +name = "html5ever" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c" +dependencies = [ + "log", + "mac", + "markup5ever 0.14.1", + "match_token", +] + [[package]] name = "http" version = "1.4.1" @@ -1077,6 +1516,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", + "webpki-roots 1.0.7", ] [[package]] @@ -1253,6 +1693,12 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "if_chain" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd62e6b5e86ea8eeeb8db1de02880a6abc01a397b2ebb64b5d74ac255318f5cb" + [[package]] name = "indexmap" version = "2.14.0" @@ -1280,6 +1726,15 @@ version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.18" @@ -1377,6 +1832,16 @@ version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + [[package]] name = "libm" version = "0.2.16" @@ -1406,6 +1871,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + [[package]] name = "linux-raw-sys" version = "0.12.1" @@ -1439,6 +1910,12 @@ version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "lzma-rust2" version = "0.16.4" @@ -1468,18 +1945,43 @@ dependencies = [ "tendril", ] +[[package]] +name = "markup5ever" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18" +dependencies = [ + "log", + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", + "tendril", +] + [[package]] name = "markup5ever_rcdom" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edaa21ab3701bfee5099ade5f7e1f84553fd19228cf332f13cd6e964bf59be18" dependencies = [ - "html5ever", - "markup5ever", + "html5ever 0.27.0", + "markup5ever 0.12.1", "tendril", "xml5ever", ] +[[package]] +name = "match_token" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "matchers" version = "0.2.0" @@ -1613,6 +2115,17 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", + "rand 0.8.6", +] + [[package]] name = "num-bigint-dig" version = "0.8.6" @@ -1624,7 +2137,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand", + "rand 0.8.6", "smallvec", "zeroize", ] @@ -1665,6 +2178,75 @@ dependencies = [ "libm", ] +[[package]] +name = "obscura-browser" +version = "0.1.0" +dependencies = [ + "anyhow", + "base64 0.22.1", + "futures", + "obscura-dom", + "obscura-js", + "obscura-net", + "serde_json", + "thiserror 2.0.18", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "obscura-dom" +version = "0.1.0" +dependencies = [ + "cssparser", + "html5ever 0.29.1", + "markup5ever 0.14.1", + "precomputed-hash", + "selectors", + "servo_arc", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "obscura-js" +version = "0.1.0" +dependencies = [ + "anyhow", + "base64 0.22.1", + "deno_core", + "deno_error", + "html5ever 0.29.1", + "obscura-dom", + "obscura-net", + "reqwest", + "serde", + "serde_json", + "sha1 0.10.6", + "sha2 0.10.9", + "thiserror 2.0.18", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "obscura-net" +version = "0.1.0" +dependencies = [ + "async-trait", + "encoding_rs", + "reqwest", + "serde", + "serde_json", + "tempfile", + "thiserror 2.0.18", + "tokio", + "tracing", + "url", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -1714,6 +2296,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "outref" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" + [[package]] name = "parking_lot" version = "0.12.5" @@ -1774,6 +2362,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ + "phf_macros", "phf_shared", ] @@ -1794,7 +2383,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand", + "rand 0.8.6", +] + +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] @@ -1806,6 +2408,26 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "pin-project-lite" version = "0.2.17" @@ -1891,6 +2513,29 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "proc-macro-rules" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07c277e4e643ef00c1233393c673f655e3672cf7eb3ba08a00bdd0ea59139b5f" +dependencies = [ + "proc-macro-rules-macros", + "proc-macro2", + "syn 2.0.117", +] + +[[package]] +name = "proc-macro-rules-macros" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "207fffb0fe655d1d47f6af98cc2793405e85929bdbc420d685554ff07be27ac7" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "proc-macro2" version = "1.0.106" @@ -1926,6 +2571,61 @@ dependencies = [ "serde", ] +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls 0.23.40", + "socket2", + "thiserror 2.0.18", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.4", + "ring", + "rustc-hash", + "rustls 0.23.40", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.45" @@ -1947,6 +2647,12 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.8.6" @@ -1954,8 +2660,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", ] [[package]] @@ -1965,7 +2681,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", ] [[package]] @@ -1977,6 +2703,15 @@ dependencies = [ "getrandom 0.2.17", ] +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + [[package]] name = "redox_syscall" version = "0.5.18" @@ -2052,6 +2787,8 @@ dependencies = [ "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls 0.23.40", "rustls-pki-types", "serde", "serde_json", @@ -2059,6 +2796,7 @@ dependencies = [ "sync_wrapper", "tokio", "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower", "tower-http 0.6.11", @@ -2068,6 +2806,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots 1.0.7", ] [[package]] @@ -2097,13 +2836,32 @@ dependencies = [ "num-traits", "pkcs1", "pkcs8", - "rand_core", + "rand_core 0.6.4", "signature", "spki", "subtle", "zeroize", ] +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.52.0", +] + [[package]] name = "rustix" version = "1.1.4" @@ -2113,7 +2871,7 @@ dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.12.1", "windows-sys 0.61.2", ] @@ -2135,6 +2893,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ "once_cell", + "ring", "rustls-pki-types", "rustls-webpki 0.103.13", "subtle", @@ -2156,6 +2915,7 @@ version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ + "web-time", "zeroize", ] @@ -2249,6 +3009,25 @@ dependencies = [ "libc", ] +[[package]] +name = "selectors" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd568a4c9bb598e291a08244a5c1f5a8a6650bee243b5b0f8dbb3d9cc1d87fe8" +dependencies = [ + "bitflags", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf", + "phf_codegen", + "precomputed-hash", + "servo_arc", + "smallvec", +] + [[package]] name = "semver" version = "1.0.28" @@ -2291,6 +3070,7 @@ version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ + "indexmap", "itoa", "memchr", "serde", @@ -2321,6 +3101,29 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_v8" +version = "0.259.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e4c5f439cffc03021c8bfd380cd1ef6acb4788a72b7e54bf4a83c73f91f8a0" +dependencies = [ + "deno_error", + "num-bigint", + "serde", + "smallvec", + "thiserror 2.0.18", + "v8", +] + +[[package]] +name = "servo_arc" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170fb83ab34de17dc69aa7c67482b22218ddb85da56546f9bd6b929e32a05930" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "sha1" version = "0.10.6" @@ -2374,6 +3177,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "shlex" version = "2.0.1" @@ -2397,7 +3206,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -2434,6 +3243,24 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "sourcemap" +version = "9.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "314d62a489431668f719ada776ca1d49b924db951b7450f8974c9ae51ab05ad7" +dependencies = [ + "base64-simd", + "bitvec", + "data-encoding", + "debugid", + "if_chain", + "rustc-hash", + "serde", + "serde_json", + "unicode-id-start", + "url", +] + [[package]] name = "spin" version = "0.9.8" @@ -2516,7 +3343,7 @@ dependencies = [ "tokio-stream", "tracing", "url", - "webpki-roots", + "webpki-roots 0.25.4", ] [[package]] @@ -2588,7 +3415,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rand", + "rand 0.8.6", "rsa", "serde", "sha1 0.10.6", @@ -2628,7 +3455,7 @@ dependencies = [ "md-5", "memchr", "once_cell", - "rand", + "rand 0.8.6", "serde", "serde_json", "sha2 0.10.9", @@ -2670,6 +3497,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "string_cache" version = "0.8.9" @@ -2695,6 +3528,12 @@ dependencies = [ "quote", ] +[[package]] +name = "stringcase" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72abeda133c49d7bddece6c154728f83eec8172380c80ab7096da9487e20d27c" + [[package]] name = "stringprep" version = "0.1.5" @@ -2706,6 +3545,27 @@ dependencies = [ "unicode-properties", ] +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "subtle" version = "2.6.1" @@ -2760,6 +3620,26 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "sys_traits" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88826d6169418c98e8bc52a43f79d50907dfa3e87ba5161930d42c6f980b35ee" +dependencies = [ + "sys_traits_macros", +] + +[[package]] +name = "sys_traits_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "181f22127402abcf8ee5c83ccd5b408933fec36a6095cf82cda545634692657e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "system-configuration" version = "0.7.0" @@ -2781,6 +3661,12 @@ dependencies = [ "libc", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tempfile" version = "3.27.0" @@ -2790,7 +3676,7 @@ dependencies = [ "fastrand", "getrandom 0.4.2", "once_cell", - "rustix", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -3030,12 +3916,17 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ + "async-compression", "bitflags", "bytes", + "futures-core", "futures-util", "http", "http-body", + "http-body-util", "pin-project-lite", + "tokio", + "tokio-util", "tower", "tower-layer", "tower-service", @@ -3172,6 +4063,12 @@ version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" +[[package]] +name = "unicode-id-start" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81b79ad29b5e19de4260020f8919b443b2ef0277d242ce532ec7b7a2cc8b6007" + [[package]] name = "unicode-ident" version = "1.0.24" @@ -3227,6 +4124,7 @@ dependencies = [ "idna", "percent-encoding", "serde", + "serde_derive", ] [[package]] @@ -3258,6 +4156,22 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "v8" +version = "137.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33995a1fee055ff743281cde33a41f0d618ee0bdbe8bdf6859e11864499c2595" +dependencies = [ + "bindgen", + "bitflags", + "fslock", + "gzip-header", + "home", + "miniz_oxide", + "paste", + "which", +] + [[package]] name = "valuable" version = "0.1.1" @@ -3276,6 +4190,12 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + [[package]] name = "walkdir" version = "2.5.0" @@ -3415,6 +4335,16 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasm_dep_analyzer" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51cf5f08b357e64cd7642ab4bbeb11aecab9e15520692129624fb9908b8df2c" +dependencies = [ + "deno_error", + "thiserror 2.0.18", +] + [[package]] name = "wasmparser" version = "0.244.0" @@ -3437,12 +4367,43 @@ 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.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" +[[package]] +name = "webpki-roots" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "which" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" +dependencies = [ + "either", + "home", + "rustix 0.38.44", + "winsafe", +] + [[package]] name = "whoami" version = "1.6.1" @@ -3453,6 +4414,22 @@ dependencies = [ "wasite", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.11" @@ -3462,6 +4439,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-core" version = "0.62.2" @@ -3680,6 +4663,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + [[package]] name = "wit-bindgen" version = "0.51.0" @@ -3780,6 +4769,15 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "xml5ever" version = "0.18.1" @@ -3788,7 +4786,7 @@ checksum = "9bbb26405d8e919bc1547a5aa9abc95cbfa438f04844f5fdd9dc7596b748bf69" dependencies = [ "log", "mac", - "markup5ever", + "markup5ever 0.12.1", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index f328aa4..afccf14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,3 +45,17 @@ flate2 = "1.1.9" zip = "8.6.0" uuid = { version = "1.23.2", features = ["v4"] } tracing-appender = "0.2.5" +obscura-browser = { path = "libs/obscura/crates/obscura-browser", optional = true } +obscura-net = { path = "libs/obscura/crates/obscura-net", optional = true } + +[features] +default = [] +obscura-inprocess = ["dep:obscura-browser", "dep:obscura-net"] + +[profile.release-min] +inherits = "release" +opt-level = "s" +lto = true +codegen-units = 1 +strip = true + diff --git a/README.md b/README.md index 0b2537c..f0196e4 100644 --- a/README.md +++ b/README.md @@ -55,11 +55,20 @@ cp .env.example .env ``` 静态资源将打包并输出在项目根目录下的 `dashboard/dist/` 目录。 2. **运行后端服务**: - ```bash - cd .. - cargo run --release - ``` - 运行后直接访问 `http://localhost:8000` 即可使用,此时所有 React 网页和后台 API 均由 Rust 进程统一分发托管,无需额外启动 Vite。 + * **方式一:外部命令行模式**(默认): + ```bash + cd .. + cargo run --release + ``` + *注意:默认模式下需下载 Obscura 二进制文件并放置在项目根目录的 `bin/` 目录下。* + * **方式二:进程内浏览器模式**(免外部二进制分发): + ```bash + cd .. + cargo run --release --features obscura-inprocess + ``` + *此时无头浏览器将直接编译进主二进制中,首次编译较慢但能一键运行。* + + 运行后直接访问 `http://localhost:8000` 即可使用,此时所有 React 网页和后台 API 均由 Rust 进程统一分发托管,无需额外启动 Vite。详细配置说明参见 [编译与部署指南](docs/deployment.md#4-obscura-两种抓取后备部署模式选择-obscura-deployment-modes)。 ### 2.3 馆藏文献健康度检查与修复 (Health Check) 系统提供内置的健康度校验脚本,可用于排查与自动修复数据库状态和物理磁盘文件的不一致问题: diff --git a/docs/deployment.md b/docs/deployment.md index f979a69..567a297 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -50,14 +50,97 @@ cargo build --release --bin health_check ```bash ./astroresearch ``` -5. 进程将默认在后台启动并监听 `http://localhost:8000` 端口。你可以通过 Nginx 将此端口反向代理到公网 80/443 端口。 + 5. 进程将默认在后台启动并监听 `http://localhost:8000` 端口。你可以通过 Nginx 将此端口反向代理到公网 80/443 端口。 --- -## 4. 环境变量配置 (Environment Variables) +## 4. Obscura 两种抓取后备部署模式选择 (Obscura Deployment Modes) + +系统集成了 `Obscura` 无头浏览器框架来作为遭遇 WAF/Cloudflare 反爬时的自动后备抓取通道。系统支持以下两种编译与部署模式: + +### 模式 A:外部命令行模式 (默认,推荐) +该模式将主 Web 服务与 V8 浏览器运行引擎相隔离,最适合常规生产环境。它拥有最快的编译时间,且进程隔离确保无头浏览器内核异常(如 OOM 或 Panic)不会拖垮主服务器。 + +1. **编译主服务**: + ```bash + cargo build --release + ``` +2. **下载/配置外部二进制**: + 从 GitHub Releases 下载编译好的 `obscura-x86_64-linux.tar.gz` 压缩包,解压后将 `obscura` 和 `obscura-worker` 两个二进制文件放到项目根目录的 `bin/` 目录下: + ```bash + mkdir -p bin/ + # 放入 bin/obscura 和 bin/obscura-worker,并赋予执行权限 + chmod +x bin/obscura bin/obscura-worker + ``` +3. **运行**: + ```bash + ./target/release/astroresearch + ``` + 当遭遇 WAF 拦截时,主进程将自动通过异步子进程调用 `./bin/obscura` 进行抓取。 + +### 模式 B:进程内集成模式 (In-Process Feature) +该模式将整个无头浏览器及 V8 运行引擎直接静态链接编译进单个二进制文件中。这免去了在服务器分发和配置外部可执行程序的步骤,提供了“零配置”的部署体验。 + +> [!WARNING] +> 由于需要静态链接 C++ 编写的 V8 引擎,**首次编译会额外多耗时 1 到 3 分钟**,且最终编译生成的**单体可执行文件体积会膨胀约 80MB**。 + +1. **启用 Feature 编译**: + 在构建时指定 `--features obscura-inprocess` 特性标记: + ```bash + cargo build --release --features obscura-inprocess + ``` +2. **运行**: + ```bash + ./target/release/astroresearch + ``` + 主服务运行期间,无需在磁盘中放置任何 `bin/obscura` 二进制。当触发反爬时,系统会在后台的专有阻塞线程池上通过独立包装的单线程 runtime 驱动进程内 V8 浏览器内核直接抓取。 + +--- + +## 5. 极致内存与体积优化部署 (Ultra-Low Memory & Size Optimization) + +对于运行在低配/低内存服务器(如 1核512M 或 1核1G 实例)的环境,系统内置了可选的编译与运行时优化策略。 + +> [!NOTE] +> 极致内存与体积优化编译配置(`release-min`)和“进程内集成模式 (In-Process Feature)”在**技术上可以完全兼容并共同启用**,但它们在**优化目标(指标)上是相互抵消(矛盾)的**。 +> 如果启用了进程内 V8 特性,C++ 静态链接库本身占用的 80MB+ 空间将无法被剔除,导致无法达成极致轻量化(~8.3MB)的体积指标;且 V8 运行时堆内存也会带来额外的物理内存开销。因此,为追求极致低资源消耗,建议在低配服务器上采用**“模式 A:外部命令行模式”**。 +> +> 如果你执意要在**进程内浏览器集成下尽可能对其体积和依赖进行优化**,可以组合使用 `--profile` 与 `--features` 参数进行编译和运行: +> ```bash +> # 编译并打包优化后的进程内单二进制文件: +> cargo build --profile release-min --features obscura-inprocess +> +> # 编译并直接运行: +> cargo run --profile release-min --features obscura-inprocess +> ``` + +### 优化指标对比: +* **二进制执行文件大小**:由 `17.0 MB` 压缩至 **`8.3 MB`**(缩减约 51%)。 +* **启动物理常驻内存 (RSS)**:由 `34.8 MB` 降至 **`32.9 MB`**(得益于词典加载后的容量自动收缩)。 +* **虚拟内存 (VSZ)**:由 `1.27 GB` 降至 **`302 MB`**(缩减约 76%)。 +* **数据段内存 (VmData)**:由 `60.1 MB` 降至 **`26.5 MB`**(缩减约 55%)。 + +### 部署优化步骤: + +1. **使用优化 Profile 进行编译**: + 在项目根目录下,使用内置的 `release-min` 编译配置: + ```bash + cargo build --profile release-min + ``` + 编译完成后的执行文件位于 `target/release-min/astroresearch`。该配置开启了 LTO(链接时优化)、剥离了调试符号,并在生成时进行了大小优化。 + +2. **限制运行时异步线程数**: + 默认情况下,异步运行时 Tokio 会根据系统的 CPU 核心数(例如 16 核)创建对应数量的 Worker 线程,这会带来很多虚拟/物理内存浪费。启动服务时,可通过注入 `TOKIO_WORKER_THREADS=1` 环境变量限制线程池大小: + ```bash + PORT=8000 TOKIO_WORKER_THREADS=1 ./astroresearch + ``` + +--- + +## 6. 环境变量配置 (Environment Variables) | 变量名 | 必需 | 默认值 | 说明 | -|:---|:---|:---|:---| +| :--- | :--- | :--- | :--- | | `DATABASE_URL` | 否 | `sqlite://library/astro_research.db` | SQLite 数据库连接 URL | | `ADS_API_KEY` | 是 | - | NASA ADS API 访问 Token | | `LLM_API_KEY` | 是 | - | 大语言模型 API Key | @@ -74,7 +157,7 @@ cargo build --release --bin health_check --- -## 5. 健康检查与维护 (Health Check) +## 7. 健康检查与维护 (Health Check) 部署后可定期运行健康检查工具排查馆藏一致性问题: diff --git a/libs/obscura b/libs/obscura new file mode 160000 index 0000000..cd889d5 --- /dev/null +++ b/libs/obscura @@ -0,0 +1 @@ +Subproject commit cd889d56596d62d561cf09301237ebf407fdd95a diff --git a/src/api/helpers.rs b/src/api/helpers.rs index 656051d..ceda91a 100644 --- a/src/api/helpers.rs +++ b/src/api/helpers.rs @@ -348,6 +348,8 @@ mod tests { has_markdown: false, has_translation: false, doctype: "article".to_string(), + pdf_error: None, + html_error: None, }; // 保存 diff --git a/src/services/download.rs b/src/services/download.rs index cf11467..02e9e59 100644 --- a/src/services/download.rs +++ b/src/services/download.rs @@ -280,6 +280,84 @@ impl Downloader { std::fs::create_dir_all(parent)?; } + #[cfg(feature = "obscura-inprocess")] + { + info!("[Obscura 后备通道] 正在运行进程内浏览器进行下载..."); + self.download_via_inprocess_obscura(url, dest_path, is_pdf).await + } + + #[cfg(not(feature = "obscura-inprocess"))] + { + info!("[Obscura 后备通道] 正在通过外部命令行子进程下载..."); + self.download_via_cli_obscura(url, dest_path, is_pdf).await + } + } + + #[cfg(feature = "obscura-inprocess")] + async fn download_via_inprocess_obscura(&self, url: &str, dest_path: &Path, is_pdf: bool) -> Result<()> { + let url_str = url.to_string(); + let dest_path_buf = dest_path.to_path_buf(); + + let handle = tokio::task::spawn_blocking(move || { + let rt = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .map_err(|e| anyhow::anyhow!("建立当前线程运行时失败: {}", e))?; + + rt.block_on(async move { + use obscura_browser::{BrowserContext, Page, lifecycle::WaitUntil}; + use std::sync::Arc; + + // 1. 初始化启用 Stealth 防检测模式的浏览器上下文 + let context = Arc::new(BrowserContext::with_full_options( + "inprocess-fetch".to_string(), + None, // 可选代理 + true, // 启用 Stealth 伪装(防指纹探测 + 广告域拦截) + None, // 默认 User-Agent + )); + + let mut page = Page::new("fetch-page".to_string(), context.clone()); + + // 2. 导航至目标 URL 并等待事件循环静默 + page.navigate_with_wait(&url_str, WaitUntil::Load).await + .map_err(|e| anyhow::anyhow!("导航失败: {:?}", e))?; + + page.settle(5000).await; // 额外静默等待 5 秒 + + // 3. 处理 PDF 与 HTML + if is_pdf { + // 对于 PDF 二进制文件,直接复用该浏览器上下文自带的 HTTP 客户端进行请求, + // 这样能确保携带相同的 Cookie 和 TLS 指纹会话 + let parsed_url = Url::parse(&url_str)?; + let response = page.http_client.fetch(&parsed_url).await + .map_err(|e| anyhow::anyhow!("获取 PDF 字节流失败: {:?}", e))?; + + std::fs::write(&dest_path_buf, &response.body)?; + validate_pdf_content(&response.body)?; + } else { + // 对于 HTML,直接从 V8 中提取 outerHTML + let val = page.evaluate("document.documentElement.outerHTML"); + let html = val.as_str().unwrap_or("").to_string(); + + std::fs::write(&dest_path_buf, &html)?; + validate_html_content(&html)?; + } + + Ok(()) + }) + }); + + match handle.await { + Ok(res) => { + info!("[Obscura 进程内后备通道] 下载并校验成功: {:?}", dest_path); + res + } + Err(e) => anyhow::bail!("进程内 Obscura 执行线程异常退出: {:?}", e), + } + } + + #[cfg(not(feature = "obscura-inprocess"))] + async fn download_via_cli_obscura(&self, url: &str, dest_path: &Path, is_pdf: bool) -> Result<()> { let mut cmd = tokio::process::Command::new("bin/obscura"); cmd.arg("fetch").arg(url).arg("--stealth"); @@ -307,7 +385,7 @@ impl Downloader { validate_html_content(&text)?; } - info!("[Obscura 后备通道] 下载并校验成功: {:?}", dest_path); + info!("[Obscura 命令行后备通道] 下载并校验成功: {:?}", dest_path); Ok(()) } @@ -1019,5 +1097,73 @@ mod tests { let _ = std::fs::remove_file(&path); Ok(()) } + + #[tokio::test] + #[ignore] + async fn test_download_via_obscura_integration() -> anyhow::Result<()> { + use axum::{Router, routing::get, response::Response as AxumResponse}; + use axum::http::{HeaderValue, header::CONTENT_TYPE}; + + // Bind to a random port + let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); + listener.set_nonblocking(true).unwrap(); + let port = listener.local_addr().unwrap().port(); + + // Build a mock PDF response + let mut pdf_data = b"%PDF-1.7 ".to_vec(); + pdf_data.extend(vec![0u8; 5100]); + pdf_data.extend(b"%%EOF"); + + let pdf_data_clone = pdf_data.clone(); + let app = Router::new() + .route("/mock.pdf", get(move || { + let p = pdf_data_clone.clone(); + async move { + AxumResponse::builder() + .header(CONTENT_TYPE, "application/pdf") + .body(axum::body::Body::from(p)) + .unwrap() + } + })) + .route("/mock.html", get(move || async { + AxumResponse::builder() + .header(CONTENT_TYPE, "text/html") + .body(axum::body::Body::from("

introduction

This is a mock paper with references and class section.
References
")) + .unwrap() + })); + + let server = axum::serve( + tokio::net::TcpListener::from_std(listener).unwrap(), + app, + ); + tokio::spawn(async move { let _ = server.await; }); + + // Temporarily set OBSCURA_ALLOW_PRIVATE_NETWORK=1 to allow loopback fetches in Obscura + std::env::set_var("OBSCURA_ALLOW_PRIVATE_NETWORK", "1"); + + let downloader = Downloader::new(); + let temp_dir = std::env::temp_dir(); + + // 1. Test HTML download via obscura + let html_dest = temp_dir.join("test_obscura_mock.html"); + let html_url = format!("http://127.0.0.1:{}/mock.html", port); + downloader.download_via_obscura(&html_url, &html_dest, false).await?; + assert!(html_dest.exists()); + let html_content = std::fs::read_to_string(&html_dest)?; + assert!(html_content.contains("introduction")); + let _ = std::fs::remove_file(&html_dest); + + // 2. Test PDF download via obscura + let pdf_dest = temp_dir.join("test_obscura_mock.pdf"); + let pdf_url = format!("http://127.0.0.1:{}/mock.pdf", port); + downloader.download_via_obscura(&pdf_url, &pdf_dest, true).await?; + assert!(pdf_dest.exists()); + let pdf_content = std::fs::read(&pdf_dest)?; + assert_eq!(pdf_content, pdf_data); + let _ = std::fs::remove_file(&pdf_dest); + + std::env::remove_var("OBSCURA_ALLOW_PRIVATE_NETWORK"); + Ok(()) + } } diff --git a/src/services/translation.rs b/src/services/translation.rs index 49036d0..8cea49d 100644 --- a/src/services/translation.rs +++ b/src/services/translation.rs @@ -47,6 +47,7 @@ impl Dictionary { } } } + self.terms.shrink_to_fit(); info!("天文词典加载成功,总计导入 {} 条专业术语对照", count); Ok(()) }