v0.36.5
This commit is contained in:
1 parent
34490fd5fc
commit
6ef01212ec
21 files changed
+204
-77
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
# RustProxy source and documentation maintenance
|
# RustProxy source and documentation maintenance
|
||||||
|
|
||||||
Current source version: **0.36.4**. The Cargo package and binary are named `rust-proxy`.
|
Current source version: **0.36.5**. The Cargo package and binary are named `rust-proxy`.
|
||||||
|
|
||||||
Before editing, read [README.md](README.md), the relevant [documentation guide](docs/README.md) and the actual code and tests. Historical release experiments are not current specifications. Use the bundled `src/admin/openapi.json` for API routes and payloads; the source implementation is authoritative for runtime behavior.
|
Before editing, read [README.md](README.md), the relevant [documentation guide](docs/README.md) and the actual code and tests. Historical release experiments are not current specifications. Use the bundled `src/admin/openapi.json` for API routes and payloads; the source implementation is authoritative for runtime behavior.
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
Release history focused on **features, settings, default behavior, compatibility and fixes**. Changes to internal code structure and preliminary performance experiments are intentionally omitted. Historical descriptions reflect their respective releases; consult the current documentation for the settings available in the latest release.
|
Release history focused on **features, settings, default behavior, compatibility and fixes**. Changes to internal code structure and preliminary performance experiments are intentionally omitted. Historical descriptions reflect their respective releases; consult the current documentation for the settings available in the latest release.
|
||||||
|
|
||||||
|
## 0.36.5 — automatic certificate choice and clearer host conflicts
|
||||||
|
|
||||||
|
- **Certificate auto-selection:** when creating a vhost, redirect or 404 host, RustProxy picks the stored certificate that covers every host name you enter (an exact name beats a wildcard, the narrowest certificate wins). A hint names the chosen certificate and the selector still lets you pick another one or the global default. Existing entries are never changed.
|
||||||
|
- **Clearer host conflicts:** the "overlapping frontend bindings for hostname …" error now names the entry that already uses the host (`vhost`, `redirect` or `404 host` plus its ID) and the conflicting listener address.
|
||||||
|
- **Clearer validation errors:** duplicate or invalid IDs, repeated hostnames, missing hostnames or listeners, invalid location IDs, regular expressions, exact paths and duplicate location matchers now say which value or location is wrong and how to fix it.
|
||||||
|
|
||||||
## 0.36.4 — cache readability and editor UX polish
|
## 0.36.4 — cache readability and editor UX polish
|
||||||
|
|
||||||
- **Cache → Domains and effectiveness:** decision counters are one compact line (`name count`, top three, the rest in a `+N` tooltip) instead of a wall of chips; the rest of the table keeps its 0.36.3 look.
|
- **Cache → Domains and effectiveness:** decision counters are one compact line (`name count`, top three, the rest in a `+N` tooltip) instead of a wall of chips; the rest of the table keeps its 0.36.3 look.
|
||||||
|
|||||||
Generated
+1
-1
@@ -1943,7 +1943,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rust-proxy"
|
name = "rust-proxy"
|
||||||
version = "0.36.4"
|
version = "0.36.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rust-proxy"
|
name = "rust-proxy"
|
||||||
version = "0.36.4"
|
version = "0.36.5"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.99.1"
|
rust-version = "1.99.1"
|
||||||
description = "RustProxy - independent reverse proxy with local administration"
|
description = "RustProxy - independent reverse proxy with local administration"
|
||||||
|
|||||||
+20
-20
@@ -1,10 +1,10 @@
|
|||||||
61bf40a0572889dc8b0dda9eae4e93e44b0de9364b3c798106c85700ffb37c23 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/.dockerignore
|
61bf40a0572889dc8b0dda9eae4e93e44b0de9364b3c798106c85700ffb37c23 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/.dockerignore
|
||||||
4140a2956264b44f259e6a37fc00ba02097bbe68b09296e04d3d243c1287129b /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/.env.example
|
4140a2956264b44f259e6a37fc00ba02097bbe68b09296e04d3d243c1287129b /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/.env.example
|
||||||
e76e688874828e3743d03693b1d2872b9633b4db09909673786caf30f7cfe489 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/.gitignore
|
e76e688874828e3743d03693b1d2872b9633b4db09909673786caf30f7cfe489 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/.gitignore
|
||||||
8007bd50f172afa9030b44e46d7c7030af387466c7c31c365dd9521a0171a58c /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/AGENTS.md
|
875fa17d64e0cf8f097cd4635ca801686c256d556680a39a9259dcdb1155ed6c /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/AGENTS.md
|
||||||
e4a89126bee0eb26f4e598f4bd6ceb38b649415afd21781071aed918948c63e3 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/CHANGELOG.md
|
a544bba6a7558f7aa780ddd3e1c9e67aae58e371dddb99e8b277455f2d4cb46b /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/CHANGELOG.md
|
||||||
ec5374a1dfe13f26d45d55e94a6e8d53a9ae9aea31d4dea8599ba07010da0a2d /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/Cargo.lock
|
eae2405a396e300ca4f2997a36239648b74acebf9e724b8c8d095c11969e3fd9 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/Cargo.lock
|
||||||
a3656e331f57811d45ab37ce4c48c069e92fb5aa9b756ffc07ce993d202d11ff /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/Cargo.toml
|
202e5377c7875ef538d420ccb563c26d4cb010dbcd49ce80ca1a1555d267b038 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/Cargo.toml
|
||||||
25c7f3c8162cbf5cc156439774118a81dae9fdc52b611ec7e40c230fc99a772c /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/Dockerfile
|
25c7f3c8162cbf5cc156439774118a81dae9fdc52b611ec7e40c230fc99a772c /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/Dockerfile
|
||||||
0d96a4ff68ad6d4b6f1f30f713b18d5184912ba8dd389f86aa7710db079abcb0 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/LICENSE
|
0d96a4ff68ad6d4b6f1f30f713b18d5184912ba8dd389f86aa7710db079abcb0 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/LICENSE
|
||||||
82d1dee2fc68158f0ea73259151461e64c8b18d807cd1fecfb1ed99dc30cf5f4 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/README.md
|
82d1dee2fc68158f0ea73259151461e64c8b18d807cd1fecfb1ed99dc30cf5f4 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/README.md
|
||||||
@@ -88,12 +88,12 @@ de6550ab8f48d556d752c252212c38ba65491fd224f972c10fbe552f91ed7520 /sessions/rcw-
|
|||||||
45be151cd85fc2ef2f1fdc3003ace63381af262e73af8a685ab48cb697cc0de1 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/integrations/routeros-oci-build/.env.routeros.example
|
45be151cd85fc2ef2f1fdc3003ace63381af262e73af8a685ab48cb697cc0de1 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/integrations/routeros-oci-build/.env.routeros.example
|
||||||
11aa102de1089ecc375f20c4bd5420fcfd3b2ef23fe0c8bdf04953fcfaf40ef0 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/integrations/routeros-oci-build/Dockerfile.routeros
|
11aa102de1089ecc375f20c4bd5420fcfd3b2ef23fe0c8bdf04953fcfaf40ef0 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/integrations/routeros-oci-build/Dockerfile.routeros
|
||||||
7c7a3e51f43b43e1c962a4b0bb591f99c1f06977bf77f23719f7f867dfe7eb8e /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/integrations/routeros-oci-build/Dockerfile.routeros.dockerignore
|
7c7a3e51f43b43e1c962a4b0bb591f99c1f06977bf77f23719f7f867dfe7eb8e /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/integrations/routeros-oci-build/Dockerfile.routeros.dockerignore
|
||||||
97b7819edfaed798a9eb51f8feed74e68c45f697e85420da8c3444e328106aa1 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/integrations/routeros-oci-build/README.md
|
8545b871df9ffb6b204f1cf30ba33fb11bd2335287982d464fa6ccd480f7c869 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/integrations/routeros-oci-build/README.md
|
||||||
3f092a9ab80221eddd67be4d1a776acbc6e04c1eb6011b588280c28e83b2582f /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/integrations/routeros-oci-build/build-routeros-oci.sh
|
3f092a9ab80221eddd67be4d1a776acbc6e04c1eb6011b588280c28e83b2582f /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/integrations/routeros-oci-build/build-routeros-oci.sh
|
||||||
3f267cafa16006e5456ade78ee2d5fae02cc7ce747839523068ffd8d7c98798a /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/integrations/routeros-oci-build/docker-entrypoint.sh
|
3f267cafa16006e5456ade78ee2d5fae02cc7ce747839523068ffd8d7c98798a /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/integrations/routeros-oci-build/docker-entrypoint.sh
|
||||||
13189fa546c3488dddd8efc80c47f6da5241e5fc28b79cbfe795414ea05c7a4f /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/langs/README.md
|
13189fa546c3488dddd8efc80c47f6da5241e5fc28b79cbfe795414ea05c7a4f /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/langs/README.md
|
||||||
d86c6082998e8c68100b16b0550454df577452fe2ff37d487b25957204463ede /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/langs/en_US.json
|
87d87fb37d3d08ae98b365db24f2fcc64b46b21c3ac5cafdad7720c16d0f3e14 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/langs/en_US.json
|
||||||
96d6cd26c0d6b425b2fc4952cc0b0b51c749ce46e7471fbb794000431a34b51a /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/langs/pl_pl.json
|
20989ca82958acaa6859af792176b653008ad962cd3de31a61a9f36000e262c0 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/langs/pl_pl.json
|
||||||
9664543e4d03422788a65e42f968c1f026c2235cb5be6fc3e0ad318997077538 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/make_zip.py
|
9664543e4d03422788a65e42f968c1f026c2235cb5be6fc3e0ad318997077538 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/make_zip.py
|
||||||
e830d37dd1f81a4b0aa7d535f5bba69e34e433b0fd99cc8ee0b296786c32379a /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/migrations/0002_admin.sql
|
e830d37dd1f81a4b0aa7d535f5bba69e34e433b0fd99cc8ee0b296786c32379a /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/migrations/0002_admin.sql
|
||||||
20112cc82192098b8d602f1c4f7ca08712e9e1366c845fabb92753187c370d35 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/migrations/0003_certificate_renewals.sql
|
20112cc82192098b8d602f1c4f7ca08712e9e1366c845fabb92753187c370d35 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/migrations/0003_certificate_renewals.sql
|
||||||
@@ -165,7 +165,7 @@ d58a2ed83319176de4e66790ed292447c9497ae031464ec55cfe27174acb639a /sessions/rcw-
|
|||||||
77b8c05645969834cc8a58e249a7b60a57d6c47ad1c5cd92ffa5e4a9b5a8e73c /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/file_logs_query.rs
|
77b8c05645969834cc8a58e249a7b60a57d6c47ad1c5cd92ffa5e4a9b5a8e73c /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/file_logs_query.rs
|
||||||
743bb7436f77e04015328a0e7e7d425e43ef8aa8d61467bde157e462c1dcdc2e /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/logging_api.rs
|
743bb7436f77e04015328a0e7e7d425e43ef8aa8d61467bde157e462c1dcdc2e /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/logging_api.rs
|
||||||
243f4a9c3fa99781e19c3952354d2632c0ce65e1dafac729567cbe3c177f94cb /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/mod.rs
|
243f4a9c3fa99781e19c3952354d2632c0ce65e1dafac729567cbe3c177f94cb /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/mod.rs
|
||||||
28fc4617820aca52a552534184b74a07c4ef09a259ac45dc754b44934cb20bef /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/openapi.json
|
73aeded6ca5a7162000e71c4fe4e210d2e9810d8b9af1877e86e43f0aa896d39 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/openapi.json
|
||||||
f7a356109786635dd58cba590c71c796dbf36b47f25845190c75ee5c6a9fcb86 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/operations.rs
|
f7a356109786635dd58cba590c71c796dbf36b47f25845190c75ee5c6a9fcb86 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/operations.rs
|
||||||
257d93a29d0bda96462bcf695aba8d0ec0f9412c379e066ec46ae8ee034e3a53 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/panel_assets.rs
|
257d93a29d0bda96462bcf695aba8d0ec0f9412c379e066ec46ae8ee034e3a53 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/panel_assets.rs
|
||||||
f5127855c2994d052678865df36d703b74f4a0afc633daf7718b10da18d26e37 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/panel_content.rs
|
f5127855c2994d052678865df36d703b74f4a0afc633daf7718b10da18d26e37 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/panel_content.rs
|
||||||
@@ -189,7 +189,7 @@ faa9735c2a02746b2954bc4955eb609f94afebb685cd5521d2629640cea2777a /sessions/rcw-
|
|||||||
aed3aea4eef0011c6b51d39736782e7d1ec52662e422f40e0c7b9ddfc19d0378 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/app/certificate-inspection.js
|
aed3aea4eef0011c6b51d39736782e7d1ec52662e422f40e0c7b9ddfc19d0378 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/app/certificate-inspection.js
|
||||||
f6b0533ffd6d0e6471519120c440619a7fb4b255854ba3dd23d81cb35cd21afb /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/app/chart-scales.js
|
f6b0533ffd6d0e6471519120c440619a7fb4b255854ba3dd23d81cb35cd21afb /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/app/chart-scales.js
|
||||||
e5b39b5592ba81292571033f26934ac0cd42bcdca7395e91094973cecb3eeaf8 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/app/config-history.js
|
e5b39b5592ba81292571033f26934ac0cd42bcdca7395e91094973cecb3eeaf8 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/app/config-history.js
|
||||||
2e4a18d1aebe9e35255ed15ba2fa17015bf5d7f3996867394aec756f2b7c67da /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/app/core.js
|
446131e27946dc32df3524e80074f99accc394c004bcfa6cf9770c1b698a0e03 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/app/core.js
|
||||||
d695ec90fb5c98c27d7ba1d2bebf54f9840985fc530efcec3fcaf48d74b36c6b /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/app/dashboard-inline-layout.js
|
d695ec90fb5c98c27d7ba1d2bebf54f9840985fc530efcec3fcaf48d74b36c6b /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/app/dashboard-inline-layout.js
|
||||||
e4238322a985d3e8b7f2de94b7af31e1c718775590b2c7b3428b878cd43337b7 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/app/dashboard-layout-editor.js
|
e4238322a985d3e8b7f2de94b7af31e1c718775590b2c7b3428b878cd43337b7 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/app/dashboard-layout-editor.js
|
||||||
a184c50e1ca6bb5a14954e31b15f09ff9978fb939064ca724851bbb4e661dc56 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/app/dashboard-presets.js
|
a184c50e1ca6bb5a14954e31b15f09ff9978fb939064ca724851bbb4e661dc56 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/app/dashboard-presets.js
|
||||||
@@ -217,7 +217,7 @@ ec3ff1b7824a7f03ee6d6b7ae9b6e0cbdb300e4891d44f982b6c04b3870f5c2b /sessions/rcw-
|
|||||||
2d703473f7b751b587c32af6954c838a3160e9efa448236b6abe291832486b72 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/css/40-editors.css
|
2d703473f7b751b587c32af6954c838a3160e9efa448236b6abe291832486b72 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/css/40-editors.css
|
||||||
87df062d7478176641364c07de396ca988a37b1a8bcb892b53cc578fe8471850 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/css/50-settings.css
|
87df062d7478176641364c07de396ca988a37b1a8bcb892b53cc578fe8471850 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/css/50-settings.css
|
||||||
eed482c4b7dd247682c135fac132bb66e501511423ca53d50e9a79f4314cbac5 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/css/60-monitoring.css
|
eed482c4b7dd247682c135fac132bb66e501511423ca53d50e9a79f4314cbac5 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/css/60-monitoring.css
|
||||||
d9ea4824dca9e355521de8d49f0dbf5fd23fa9c0d9a91fb8719498858cb1a80e /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/css/70-responsive.css
|
83cb48e2e4748bff2260dc7d9d84e922781d35812eecb4d2e34831cebb21d015 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/css/70-responsive.css
|
||||||
8009afdb04d5170687816730cc930a22fead1fe0248835ca7e8de81d6907395d /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/css/README.md
|
8009afdb04d5170687816730cc930a22fead1fe0248835ca7e8de81d6907395d /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/css/README.md
|
||||||
8241bd9489dfed082863948829a44a49bf0a8e9cd63c55809655109e393e0918 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/css/manifest.json
|
8241bd9489dfed082863948829a44a49bf0a8e9cd63c55809655109e393e0918 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/css/manifest.json
|
||||||
ee51ab0912e0ade6a3e1c2ea6f533bb2f65a6d3e6ec9087e25b9f0df009c19b2 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/dashboard-defaults.json
|
ee51ab0912e0ade6a3e1c2ea6f533bb2f65a6d3e6ec9087e25b9f0df009c19b2 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/dashboard-defaults.json
|
||||||
@@ -243,7 +243,7 @@ e6c4d91d1542d0a5b47bb8736f9539d43a6713df5a473b635519d5b7eac2eb9c /sessions/rcw-
|
|||||||
003d382cc8dd69ad7237679632c04a9389366bb71dd7dca8ee64ee06614aa9a5 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/error_auth_provider.html
|
003d382cc8dd69ad7237679632c04a9389366bb71dd7dca8ee64ee06614aa9a5 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/error_auth_provider.html
|
||||||
0a5fff35555153f59d4346933030a67b6e1a8768cee7a47cfa2fcf1a2c564f63 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/favicon.svg
|
0a5fff35555153f59d4346933030a67b6e1a8768cee7a47cfa2fcf1a2c564f63 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/favicon.svg
|
||||||
7cbdef9192a9dee1f8eac42b85f52b3190f7f6efae50004aa7ad116a910e4036 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/file-logs.js
|
7cbdef9192a9dee1f8eac42b85f52b3190f7f6efae50004aa7ad116a910e4036 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/file-logs.js
|
||||||
cc9bcae4d2fe37f64cb2dfdd4d91d59bdf6fee27049896f33b899555b30e7f2c /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/host404.js
|
14377f09e0fd04cca00c4ca58c3a243b10ddb43dcbd0faf58a57209303d73d8e /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/host404.js
|
||||||
0a7bd0afcc0f65fced7dcfc1dfa1469a8ed6051af274701c23f94885d8e9107d /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/index.html
|
0a7bd0afcc0f65fced7dcfc1dfa1469a8ed6051af274701c23f94885d8e9107d /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/index.html
|
||||||
7979c490b7fcfcd8f5e52e99fcf7757d78509337a625341c98f62c6da50da374 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/integrations.js
|
7979c490b7fcfcd8f5e52e99fcf7757d78509337a625341c98f62c6da50da374 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/integrations.js
|
||||||
7a12f020fc587205694978ab41b660e9a80487d413fbf6e34fc525eabc58308f /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/login-keys.json
|
7a12f020fc587205694978ab41b660e9a80487d413fbf6e34fc525eabc58308f /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/login-keys.json
|
||||||
@@ -253,14 +253,14 @@ a74b0d8d9a5aedb4d1ee4b7f7805693ee3cf2152054e35a310bd72e81ea1ca4f /sessions/rcw-
|
|||||||
1f3d10e389c9c20e6eb019509fa6e82b50c6b43bbf988c1210a4d42bb73985d0 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/partials/overview-charts.html
|
1f3d10e389c9c20e6eb019509fa6e82b50c6b43bbf988c1210a4d42bb73985d0 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/partials/overview-charts.html
|
||||||
32b3f9b3ce9d1de928d2f23265d09b65a135fd045d1d24b98e830922be21432f /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/partials/overview-metrics.html
|
32b3f9b3ce9d1de928d2f23265d09b65a135fd045d1d24b98e830922be21432f /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/partials/overview-metrics.html
|
||||||
3928afce2ed6d5f2d3e29475dd29e4c3bd3c6df180ad5119beaff0c7a58e3b3b /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/prometheus-token.js
|
3928afce2ed6d5f2d3e29475dd29e4c3bd3c6df180ad5119beaff0c7a58e3b3b /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/prometheus-token.js
|
||||||
ff8222eae4e11a3d85b77705128e064aa6c8cafc83afcd3dc194299a3dbf3911 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/redirects.js
|
a5c05ab544c7e1ea96f2fd133b55adfd8036837036bed3007259070a6a68e38f /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/redirects.js
|
||||||
76a01f590d49649dcb1f554c221290919b2a8438e6001737f3c096fa6daec74d /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/settings.js
|
76a01f590d49649dcb1f554c221290919b2a8438e6001737f3c096fa6daec74d /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/settings.js
|
||||||
8eadbada619b15087783dcfa0e889a81f88e78034d084c5ab616f7912b835940 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/status_200.html
|
8eadbada619b15087783dcfa0e889a81f88e78034d084c5ab616f7912b835940 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/status_200.html
|
||||||
792d59e169991749bd119ec6acb9386182f4fc9be1705e5f9f3f24d7d2bfc057 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/streams.js
|
792d59e169991749bd119ec6acb9386182f4fc9be1705e5f9f3f24d7d2bfc057 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/streams.js
|
||||||
ae0259cf32f53d69a22a640b1c34562018d4ffb3864494012de3a31c0bb4ac1e /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/traffic-panel.js
|
ae0259cf32f53d69a22a640b1c34562018d4ffb3864494012de3a31c0bb4ac1e /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/traffic-panel.js
|
||||||
675ea169d4cc55fda5e291af536338b882bede1eaa6c9d5cc7dfde0779c7c4d1 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/transform-panel.js
|
675ea169d4cc55fda5e291af536338b882bede1eaa6c9d5cc7dfde0779c7c4d1 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/transform-panel.js
|
||||||
87917b0388090f2b27ec6460be56fea96dc09b42735319e0a91330748848e288 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/vhosts/core.js
|
87917b0388090f2b27ec6460be56fea96dc09b42735319e0a91330748848e288 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/vhosts/core.js
|
||||||
28961dba1537265f795911bfc6826065ab00b154a295f47f5b78b9235a06d43d /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/vhosts/editor.js
|
141565fbd8d2dceaa9b6f488046b96c897c94d475450db22ce854ce534336318 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/vhosts/editor.js
|
||||||
3776f72d7051af86ac5fbdd4581040dd88a424c0c6cde789301b032b159094d8 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/vhosts/health.js
|
3776f72d7051af86ac5fbdd4581040dd88a424c0c6cde789301b032b159094d8 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/vhosts/health.js
|
||||||
b3239e67901f1796d7a974ade0796f2e3590ff8064628a5629b78c7f6ce2f32e /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/vhosts/protocol.js
|
b3239e67901f1796d7a974ade0796f2e3590ff8064628a5629b78c7f6ce2f32e /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/vhosts/protocol.js
|
||||||
8c3da49973c62333559b0e3588c02beb0b425c025eac5cfa82a1bb968f70d9dd /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/vhosts/rates.js
|
8c3da49973c62333559b0e3588c02beb0b425c025eac5cfa82a1bb968f70d9dd /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/admin/web/vhosts/rates.js
|
||||||
@@ -339,12 +339,12 @@ a1132b980833b1b4ce2bba9aa681ff255a0e2d61faaa65a316860da503ea1e27 /sessions/rcw-
|
|||||||
1a2eb6684d9ea4a7e90970d936c75f7c8bbec46a4181fdf273be9bdac8eec847 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/compression/mod.rs
|
1a2eb6684d9ea4a7e90970d936c75f7c8bbec46a4181fdf273be9bdac8eec847 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/compression/mod.rs
|
||||||
8de82d9188c9c337690c6ec4afdad9fff20651c358e34602a93d8bb8c3d2489a /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/compression/tests.rs
|
8de82d9188c9c337690c6ec4afdad9fff20651c358e34602a93d8bb8c3d2489a /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/compression/tests.rs
|
||||||
e695079333ebdc2a6e7b3337cfabef171b3a0a01da0597b77feff70d417f833e /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config.rs
|
e695079333ebdc2a6e7b3337cfabef171b3a0a01da0597b77feff70d417f833e /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config.rs
|
||||||
d727e5ebd6c6184943d5f773c6b5244954832139c744851c1357614880f09c6d /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/backend.rs
|
2c4312dd7410dc231ed204d7d201d716eedb41045fd95df7cbb51d5561540d99 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/backend.rs
|
||||||
367b46f2b57143db17044378b1f5a55bab1eae3ad6ba40f388896995d1b2a13d /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/compile.rs
|
6ad644fc4ae821d2c30329ace36652a7ac12d674e71e7dbdcdda3554c983f6f9 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/compile.rs
|
||||||
fbea01fea1213d98aea812c1b78d5db289e09200b98ae514d742235cd3fa70e1 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/internal_routing.rs
|
fbea01fea1213d98aea812c1b78d5db289e09200b98ae514d742235cd3fa70e1 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/internal_routing.rs
|
||||||
cc75698be2828000e88f2c482bd26f2fa4050e3432bec1b5a581dca17fef4a37 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/model.rs
|
cc75698be2828000e88f2c482bd26f2fa4050e3432bec1b5a581dca17fef4a37 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/model.rs
|
||||||
75839458ddbc7480ec4492a95eeb67b617ba7d62f7b67e7a767a3453b74dbcbc /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/route_policy_tests.rs
|
75839458ddbc7480ec4492a95eeb67b617ba7d62f7b67e7a767a3453b74dbcbc /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/route_policy_tests.rs
|
||||||
736b46108c72220b8142f4f2ab128876b6bd82e0d09891578abdce6aa03c82f3 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/routing.rs
|
e442c6561723e8dbf73d25912227cebf7aa84ac1523e8bda8e6b4bdad1b674df /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/routing.rs
|
||||||
dd9a6ad8f58e0cdd1ae74f3f972fee0ac14383cd8b8f518403b9a36c169f35bd /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/snapshot.rs
|
dd9a6ad8f58e0cdd1ae74f3f972fee0ac14383cd8b8f518403b9a36c169f35bd /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/snapshot.rs
|
||||||
477cddaa1e1c0b9b605a2f550971a04cf30287519cba70cfbb2e1860e3a93ff2 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/tests.rs
|
477cddaa1e1c0b9b605a2f550971a04cf30287519cba70cfbb2e1860e3a93ff2 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/tests.rs
|
||||||
f35de0ee1516ece6bbfd2b2a7db7d1e0f5048b0ec47cf2a3765dffb799abfd93 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/transport_tests.rs
|
f35de0ee1516ece6bbfd2b2a7db7d1e0f5048b0ec47cf2a3765dffb799abfd93 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/config/transport_tests.rs
|
||||||
@@ -400,7 +400,7 @@ a719c51aebcba0f16f8810c37618201954e79d6806da085ee6c5e4697a05b521 /sessions/rcw-
|
|||||||
31154052757c2bb975b8ce8cad67f3fad7b5132b615a73d5b0d7bf1b5311722b /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/metrics/rate_sampling.rs
|
31154052757c2bb975b8ce8cad67f3fad7b5132b615a73d5b0d7bf1b5311722b /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/metrics/rate_sampling.rs
|
||||||
f27f1f8bed769883d1a7ae6a48f89f7712394dfab65d05702b0f944f0a45bd8e /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/metrics/vhost/mod.rs
|
f27f1f8bed769883d1a7ae6a48f89f7712394dfab65d05702b0f944f0a45bd8e /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/metrics/vhost/mod.rs
|
||||||
ee401f943bd8b2706c33419ed69102269c08dcb4ceba6f4be2ac0861115874a7 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/metrics/vhost/tests.rs
|
ee401f943bd8b2706c33419ed69102269c08dcb4ceba6f4be2ac0861115874a7 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/metrics/vhost/tests.rs
|
||||||
9c96c3e4edb20dd0c36b5c373f1925dd60368e75853002206523072d418d5417 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/not_found/mod.rs
|
f2a632f9d3d7f9985ff796545263ebe03fbf5e9a5c2e88288e89a700d3af81d3 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/not_found/mod.rs
|
||||||
fa2fc6c6987a8356a9da92cade10db62426d8863e9cef3c0d4324c45780c5b33 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/not_found/tests.rs
|
fa2fc6c6987a8356a9da92cade10db62426d8863e9cef3c0d4324c45780c5b33 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/not_found/tests.rs
|
||||||
c19998732c2d65b464f43d17a58644db5bcf7b4a6dd4c31a65a091c57692a5bb /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/oidc/mod.rs
|
c19998732c2d65b464f43d17a58644db5bcf7b4a6dd4c31a65a091c57692a5bb /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/oidc/mod.rs
|
||||||
c4dbe0f8ded237d45b6a3977bdc7544296e4408996815cae9e28af028419d0b7 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/oidc/tests.rs
|
c4dbe0f8ded237d45b6a3977bdc7544296e4408996815cae9e28af028419d0b7 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/oidc/tests.rs
|
||||||
@@ -456,7 +456,7 @@ a44421714aab37f7ceda19e3ec2512c645d2a3ce5dcb3da5bc7a0d87a442d6a8 /sessions/rcw-
|
|||||||
999cbf85cb6e917db529e30ba4a5eed1cc9e95a054da7b3039c730bb80061449 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/proxy/websocket/validation.rs
|
999cbf85cb6e917db529e30ba4a5eed1cc9e95a054da7b3039c730bb80061449 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/proxy/websocket/validation.rs
|
||||||
80d0f744f7ad9f0d1edeb0d5c23b13cb40431f6b6f4d10d534ed34d4198e3dfd /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/rate_limit/mod.rs
|
80d0f744f7ad9f0d1edeb0d5c23b13cb40431f6b6f4d10d534ed34d4198e3dfd /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/rate_limit/mod.rs
|
||||||
c85c9f05dac65cde6878bef3ef7258eb9de79ca14c26ca2492e0e13839c40fc3 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/rate_limit/tests.rs
|
c85c9f05dac65cde6878bef3ef7258eb9de79ca14c26ca2492e0e13839c40fc3 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/rate_limit/tests.rs
|
||||||
e53c40b85792d4804a432e3c97dc13af8e29304bb0d250ee9ab9018bde522eeb /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/redirect/mod.rs
|
db254128c8013adaad7280f40a0edd8b196083afef299cd9e193e6db1d698b82 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/redirect/mod.rs
|
||||||
811c83ae9fd0f5a13d35b5443cd37843f82b9d600bee4bb136ba9b87732a5347 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/redirect/tests.rs
|
811c83ae9fd0f5a13d35b5443cd37843f82b9d600bee4bb136ba9b87732a5347 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/redirect/tests.rs
|
||||||
244d72b3dab36ec505c96d26a967420714fd3807268820f680fb3dcea0e88c0f /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/runtime.rs
|
244d72b3dab36ec505c96d26a967420714fd3807268820f680fb3dcea0e88c0f /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/runtime.rs
|
||||||
3c71d8eef9ccb49ad93cf6014c5c27756ce0eaeddfca116048f24c483fda68e2 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/runtime/certificates.rs
|
3c71d8eef9ccb49ad93cf6014c5c27756ce0eaeddfca116048f24c483fda68e2 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/runtime/certificates.rs
|
||||||
@@ -531,7 +531,7 @@ d61c427c1e9cf457f1232b822d73e846e9f329cfbe61215e7ca061d53762155d /sessions/rcw-
|
|||||||
a8c5ec5095178a0656a001b0d7100e240d1f32b052ea60df37f8681269638ab3 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/vhost/model.rs
|
a8c5ec5095178a0656a001b0d7100e240d1f32b052ea60df37f8681269638ab3 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/vhost/model.rs
|
||||||
fc8af7342a3b147921e9040116af5dfe680b3df910db2416ada18198bbeea7df /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/vhost/redirect.rs
|
fc8af7342a3b147921e9040116af5dfe680b3df910db2416ada18198bbeea7df /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/vhost/redirect.rs
|
||||||
2651d7e3e3fadf3de74a75eafe2bbad8d02939551ccc0504c1a092a0b33b0db5 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/vhost/tests.rs
|
2651d7e3e3fadf3de74a75eafe2bbad8d02939551ccc0504c1a092a0b33b0db5 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/vhost/tests.rs
|
||||||
190b2bbdc7ef5181ae4dbe1659f6f0c7ead5d09936b109d0c5be7ea2e7edd681 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/vhost/validation.rs
|
c32ff8fae0c291bf072404aa118cb81016752b2929c89c7ec845d97006e677ce /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/vhost/validation.rs
|
||||||
8d1eff4b24f01d137414ef5419f75dd281879228adb70409645b11b3c78c20e9 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/web_server/config.rs
|
8d1eff4b24f01d137414ef5419f75dd281879228adb70409645b11b3c78c20e9 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/web_server/config.rs
|
||||||
9744e8c29ae72a4d9fbc9a76166a97f8292c4c312295ea40d1cb699e03d80a9d /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/web_server/config/compile.rs
|
9744e8c29ae72a4d9fbc9a76166a97f8292c4c312295ea40d1cb699e03d80a9d /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/web_server/config/compile.rs
|
||||||
5ed79fa5b9c53f95ca200d89a9ba927dda816b61fbdf3b852bd3c9670e3d2d4f /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/web_server/config/model.rs
|
5ed79fa5b9c53f95ca200d89a9ba927dda816b61fbdf3b852bd3c9670e3d2d4f /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/src/web_server/config/model.rs
|
||||||
@@ -561,7 +561,7 @@ f00743af2cf4a5952caef7a1dcf68e7817b5599a252a9973e1c22045517c0b0e /sessions/rcw-
|
|||||||
102b83171a6429b6375d8001d6c5294702385cd58ee55727cb657b1f3566e877 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/tests/panel_icons_browser.py
|
102b83171a6429b6375d8001d6c5294702385cd58ee55727cb657b1f3566e877 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/tests/panel_icons_browser.py
|
||||||
52e61c389a60d147184ee76925cac76e454f8f2e3cb91039bb06e17787ab900f /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/tests/panel_icons_contract.js
|
52e61c389a60d147184ee76925cac76e454f8f2e3cb91039bb06e17787ab900f /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/tests/panel_icons_contract.js
|
||||||
01af3008be27fabb486c141c67099af104f2725cc56f4c656aea9741a3c150cd /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/tests/panel_interface_contract.py
|
01af3008be27fabb486c141c67099af104f2725cc56f4c656aea9741a3c150cd /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/tests/panel_interface_contract.py
|
||||||
2346b7de3a705e1128794fa89ce4811cdf240e1105f982520f3c4eed1358eafa /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/tests/panel_refresh_contract.js
|
e7b9656dc584e441ca50ac289ec0fd9a37ffc4e7872c486f683e6712c806b9bd /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/tests/panel_refresh_contract.js
|
||||||
e24a0f84f1bfc46964df865ac387d651f7b384d781cbc8f3a9a5b0b60f3d69ca /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/tests/vhost_auth_selection.js
|
e24a0f84f1bfc46964df865ac387d651f7b384d781cbc8f3a9a5b0b60f3d69ca /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/tests/vhost_auth_selection.js
|
||||||
eca68a07c2b1e45fdb8f512294f5a432db3ae5a6aec8fb200b47f155cd9a31d6 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/tools/README.md
|
eca68a07c2b1e45fdb8f512294f5a432db3ae5a6aec8fb200b47f155cd9a31d6 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/tools/README.md
|
||||||
7c30c280d0b0a8bf855eeffab583ca34dc161255f7ef6124148aa979c17c26d3 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/tools/dev/memory_load.py
|
7c30c280d0b0a8bf855eeffab583ca34dc161255f7ef6124148aa979c17c26d3 /sessions/rcw-01mmsgszuju6d7f2h8egrxc4/mnt/RustProxy/tools/dev/memory_load.py
|
||||||
|
|||||||
@@ -77,10 +77,10 @@ ENV_FILE=integrations/routeros-oci-build/.env \
|
|||||||
bash integrations/routeros-oci-build/build-routeros-oci.sh push
|
bash integrations/routeros-oci-build/build-routeros-oci.sh push
|
||||||
```
|
```
|
||||||
|
|
||||||
For example, with RustProxy version `0.36.4` and the defaults this publishes:
|
For example, with RustProxy version `0.36.5` and the defaults this publishes:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
zot.example.net/network/rustproxy:0.36.4
|
zot.example.net/network/rustproxy:0.36.5
|
||||||
zot.example.net/network/rustproxy:latest
|
zot.example.net/network/rustproxy:latest
|
||||||
zot.example.net/network/rustproxy:routeros
|
zot.example.net/network/rustproxy:routeros
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1732,6 +1732,7 @@
|
|||||||
"autoIdChange": "Change",
|
"autoIdChange": "Change",
|
||||||
"autoIdPending": "Generated from the name",
|
"autoIdPending": "Generated from the name",
|
||||||
"autoIdBadge": "auto",
|
"autoIdBadge": "auto",
|
||||||
|
"autoCertHint": "Certificate \"{id}\" was selected automatically because it covers all host names. You can choose another one.",
|
||||||
"dockerLiveAccessLogsHelp": "Live HTTP access logs for this Docker vhost, not the container stdout/stderr.",
|
"dockerLiveAccessLogsHelp": "Live HTTP access logs for this Docker vhost, not the container stdout/stderr.",
|
||||||
"networkInterfacesHistory": "Traffic by interface",
|
"networkInterfacesHistory": "Traffic by interface",
|
||||||
"networkInterfaceRate": "RX / TX",
|
"networkInterfaceRate": "RX / TX",
|
||||||
|
|||||||
@@ -1732,6 +1732,7 @@
|
|||||||
"autoIdChange": "Zmień",
|
"autoIdChange": "Zmień",
|
||||||
"autoIdPending": "Generowane z nazwy",
|
"autoIdPending": "Generowane z nazwy",
|
||||||
"autoIdBadge": "auto",
|
"autoIdBadge": "auto",
|
||||||
|
"autoCertHint": "Certyfikat \"{id}\" został wybrany automatycznie, bo pokrywa wszystkie nazwy hostów. Możesz wybrać inny.",
|
||||||
"dockerLiveAccessLogsHelp": "Logi żądań HTTP dla tego Docker vhosta, nie stdout/stderr kontenera.",
|
"dockerLiveAccessLogsHelp": "Logi żądań HTTP dla tego Docker vhosta, nie stdout/stderr kontenera.",
|
||||||
"networkInterfacesHistory": "Ruch według interfejsów",
|
"networkInterfacesHistory": "Ruch według interfejsów",
|
||||||
"networkInterfaceRate": "RX / TX",
|
"networkInterfaceRate": "RX / TX",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"openapi": "3.0.3",
|
"openapi": "3.0.3",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "RustProxy Administration API",
|
"title": "RustProxy Administration API",
|
||||||
"version": "0.36.4",
|
"version": "0.36.5",
|
||||||
"description": "Administration API for the active panel origin. Sign in through the panel; the same-origin HttpOnly cookie authenticates all private operations. Mutations also require the exact Origin, X-RustProxy-Request: 1 and a session-bound X-CSRF-Token. Loopback HTTP is the default; Settings can enable HTTPS before using a non-loopback administration bind. This document contains no live configuration or credentials. Object schemas marked extensible are summaries: full configuration validation is authoritative in Rust. The API also permits explicitly scoped GeneralApiBearer tokens on a narrow route allowlist, with RO/RW and source CIDR checks; API-token management and Prometheus-token management are browser-session-only."
|
"description": "Administration API for the active panel origin. Sign in through the panel; the same-origin HttpOnly cookie authenticates all private operations. Mutations also require the exact Origin, X-RustProxy-Request: 1 and a session-bound X-CSRF-Token. Loopback HTTP is the default; Settings can enable HTTPS before using a non-loopback administration bind. This document contains no live configuration or credentials. Object schemas marked extensible are summaries: full configuration validation is authoritative in Rust. The API also permits explicitly scoped GeneralApiBearer tokens on a narrow route allowlist, with RO/RW and source CIDR checks; API-token management and Prometheus-token management are browser-session-only."
|
||||||
},
|
},
|
||||||
"servers": [
|
"servers": [
|
||||||
|
|||||||
@@ -727,3 +727,56 @@ const rustProxyAutoId = (() => {
|
|||||||
return { slugify, unique, attach };
|
return { slugify, unique, attach };
|
||||||
})();
|
})();
|
||||||
window.rustProxyAutoId = rustProxyAutoId;
|
window.rustProxyAutoId = rustProxyAutoId;
|
||||||
|
|
||||||
|
// Automatic certificate choice: for a new entry, pick the stored certificate that covers every host name (exact names beat wildcards); the user can still choose another one.
|
||||||
|
const rustProxyAutoCertificate = (() => {
|
||||||
|
const states = new WeakMap();
|
||||||
|
const covers = (pattern, host) => {
|
||||||
|
pattern = String(pattern).toLowerCase(); host = String(host).toLowerCase();
|
||||||
|
if (pattern === host) return true;
|
||||||
|
if (host.startsWith("*.") || !pattern.startsWith("*.")) return false;
|
||||||
|
const suffix = pattern.slice(1);
|
||||||
|
return host.length > suffix.length && host.endsWith(suffix) && !host.slice(0, -suffix.length).includes(".");
|
||||||
|
};
|
||||||
|
function suggest(hosts, certificates) {
|
||||||
|
const names = [...new Set((hosts || []).map(host => String(host).trim().toLowerCase()).filter(Boolean))];
|
||||||
|
if (!names.length) return "";
|
||||||
|
let best = "", bestScore = -Infinity;
|
||||||
|
for (const cert of certificates || []) {
|
||||||
|
const coverage = certificateInventory.get(cert.id)?.covered_hosts?.length ? certificateInventory.get(cert.id).covered_hosts : (cert.covered_hosts || []);
|
||||||
|
let score = 0, all = true;
|
||||||
|
for (const host of names) {
|
||||||
|
if (coverage.some(pattern => String(pattern).toLowerCase() === host)) score += 2;
|
||||||
|
else if (coverage.some(pattern => covers(pattern, host))) score += 1;
|
||||||
|
else { all = false; break; }
|
||||||
|
}
|
||||||
|
if (!all) continue;
|
||||||
|
score -= coverage.length / 1000;
|
||||||
|
if (score > bestScore) { best = cert.id; bestScore = score; }
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
// options: { hosts: () => host names, certificates: () => certificate objects, auto: boolean, anchor: element after which the hint is placed }
|
||||||
|
function attach(select, options) {
|
||||||
|
let state = states.get(select);
|
||||||
|
if (!state) {
|
||||||
|
state = { hint: document.createElement("small") };
|
||||||
|
state.hint.className = "fine auto-cert-hint"; state.hint.hidden = true;
|
||||||
|
(options.anchor || select).after(state.hint);
|
||||||
|
select.addEventListener("change", event => { if (!event.isTrusted) return; const current = states.get(select); current.auto = false; current.hint.hidden = true; });
|
||||||
|
states.set(select, state);
|
||||||
|
}
|
||||||
|
state.options = options; state.auto = options.auto !== false && !select.value; state.hint.hidden = true;
|
||||||
|
const refresh = hosts => {
|
||||||
|
const current = states.get(select);
|
||||||
|
if (!current.auto) return;
|
||||||
|
const list = hosts || current.options.hosts();
|
||||||
|
const best = suggest(list, current.options.certificates());
|
||||||
|
if (select.value !== best) { select.value = best; select.dispatchEvent(new Event("change", { bubbles: true })); }
|
||||||
|
current.hint.hidden = !best; current.hint.textContent = best ? t("autoCertHint").replace("{id}", best) : "";
|
||||||
|
};
|
||||||
|
return { refresh };
|
||||||
|
}
|
||||||
|
return { attach, suggest, covers };
|
||||||
|
})();
|
||||||
|
window.rustProxyAutoCertificate = rustProxyAutoCertificate;
|
||||||
@@ -1767,9 +1767,9 @@
|
|||||||
.vh-setting-section>h3 { letter-spacing: .01em; }
|
.vh-setting-section>h3 { letter-spacing: .01em; }
|
||||||
.vh-tabs { flex-wrap: wrap; overflow: visible; row-gap: 0; }
|
.vh-tabs { flex-wrap: wrap; overflow: visible; row-gap: 0; }
|
||||||
@media (max-width:700px) { .vh-tabs button { font-size: 11px; padding: 7px 8px; } }
|
@media (max-width:700px) { .vh-tabs button { font-size: 11px; padding: 7px 8px; } }
|
||||||
.auto-id-hint { display: block; margin-top: 3px; color: var(--muted); font-size: 11px; line-height: 1.35; }
|
.auto-id-hint, .auto-cert-hint { display: block; margin-top: 3px; color: var(--muted); font-size: 11px; line-height: 1.35; }
|
||||||
.auto-id-reset { justify-self: start; margin-top: 3px; padding: 2px 8px; font-size: 11px; }
|
.auto-id-reset { justify-self: start; margin-top: 3px; padding: 2px 8px; font-size: 11px; }
|
||||||
.auto-id-hint[hidden], .auto-id-reset[hidden] { display: none; }
|
.auto-id-hint[hidden], .auto-cert-hint[hidden], .auto-id-reset[hidden] { display: none; }
|
||||||
.auto-id-field>span:first-child { color: var(--muted); }
|
.auto-id-field>span:first-child { color: var(--muted); }
|
||||||
.auto-id-field.is-compact>input { display: none; }
|
.auto-id-field.is-compact>input { display: none; }
|
||||||
.auto-id-row { display: flex; align-items: center; gap: 8px; min-height: 32px; padding: 0 2px; }
|
.auto-id-row { display: flex; align-items: center; gap: 8px; min-height: 32px; padding: 0 2px; }
|
||||||
@@ -1779,6 +1779,3 @@
|
|||||||
.auto-id-change { padding: 2px 8px; font-size: 11px; margin-left: auto; }
|
.auto-id-change { padding: 2px 8px; font-size: 11px; margin-left: auto; }
|
||||||
.auto-id-row[hidden], .auto-id-change[hidden], .auto-id-badge[hidden] { display: none; }
|
.auto-id-row[hidden], .auto-id-change[hidden], .auto-id-badge[hidden] { display: none; }
|
||||||
.auto-id-field input { font-family: var(--mono, monospace); font-size: 12px; }
|
.auto-id-field input { font-family: var(--mono, monospace); font-size: 12px; }
|
||||||
.auto-id-hint { display: block; margin-top: 3px; color: var(--muted); font-size: 11px; line-height: 1.35; }
|
|
||||||
.auto-id-reset { justify-self: start; margin-top: 3px; padding: 2px 8px; font-size: 11px; }
|
|
||||||
.auto-id-hint[hidden], .auto-id-reset[hidden] { display: none; }
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
const form = $("notfound-form"), dialog = $("notfound-dialog"), list = $("notfound-list");
|
const form = $("notfound-form"), dialog = $("notfound-dialog"), list = $("notfound-list");
|
||||||
if (!form || !dialog || !list) return;
|
if (!form || !dialog || !list) return;
|
||||||
const sortColumns = ["id", "name", "hostname", "status", "mode", "listeners", "certificate"];
|
const sortColumns = ["id", "name", "hostname", "status", "mode", "listeners", "certificate"];
|
||||||
let editing = null, revision = null, dirty = false, readBindings = () => [], readHosts = () => [], listPrefs = { sort: "id", descending: false };
|
let notFoundAutoCertificate = null, editing = null, revision = null, dirty = false, readBindings = () => [], readHosts = () => [], listPrefs = { sort: "id", descending: false };
|
||||||
function normalizeListPrefs(preferences) { return { sort: sortColumns.includes(preferences?.notfound_list_sort) ? preferences.notfound_list_sort : "id", descending: preferences?.notfound_list_descending === true }; }
|
function normalizeListPrefs(preferences) { return { sort: sortColumns.includes(preferences?.notfound_list_sort) ? preferences.notfound_list_sort : "id", descending: preferences?.notfound_list_descending === true }; }
|
||||||
function syncSortDirection() { const control = $("notfound-sort-direction"); if (!control) return; control.textContent = listPrefs.descending ? "↓" : "↑"; control.setAttribute("aria-label", t(listPrefs.descending ? "backendSortDescending" : "backendSortAscending")); }
|
function syncSortDirection() { const control = $("notfound-sort-direction"); if (!control) return; control.textContent = listPrefs.descending ? "↓" : "↑"; control.setAttribute("aria-label", t(listPrefs.descending ? "backendSortDescending" : "backendSortAscending")); }
|
||||||
function applyPreferences(preferences) { listPrefs = normalizeListPrefs(preferences); if ($("notfound-sort")) $("notfound-sort").value = listPrefs.sort; syncSortDirection(); render(); }
|
function applyPreferences(preferences) { listPrefs = normalizeListPrefs(preferences); if ($("notfound-sort")) $("notfound-sort").value = listPrefs.sort; syncSortDirection(); render(); }
|
||||||
@@ -46,8 +46,9 @@
|
|||||||
$("notfound-id").value = item.id || ""; $("notfound-id").disabled = Boolean(editing); $("notfound-name").value = item.name || "";
|
$("notfound-id").value = item.id || ""; $("notfound-id").disabled = Boolean(editing); $("notfound-name").value = item.name || "";
|
||||||
window.rustProxyAutoId.attach($("notfound-id"), { elements: [$("notfound-name")], taken: () => (envelope?.config.not_found_hosts || []).map(value => value.id) });
|
window.rustProxyAutoId.attach($("notfound-id"), { elements: [$("notfound-name")], taken: () => (envelope?.config.not_found_hosts || []).map(value => value.id) });
|
||||||
$("notfound-enabled").checked = item.enabled !== false; syncEnabledControl(); $("notfound-http2").checked = item.http2_enabled !== false; $("notfound-http3").checked = item.http3_enabled !== false;
|
$("notfound-enabled").checked = item.enabled !== false; syncEnabledControl(); $("notfound-http2").checked = item.http2_enabled !== false; $("notfound-http3").checked = item.http3_enabled !== false;
|
||||||
const hostHolder = $("notfound-hosts-editor"); hostHolder.replaceChildren(); readHosts = window.rustProxyIntegrations.hostnames(hostHolder, item.frontend?.hosts || [], { labelKey: "notfoundHosts", helpKey: "vhHostsHelp", requiredKey: "notfoundHostsRequired", onChange: changed });
|
const hostHolder = $("notfound-hosts-editor"); hostHolder.replaceChildren(); readHosts = window.rustProxyIntegrations.hostnames(hostHolder, item.frontend?.hosts || [], { labelKey: "notfoundHosts", helpKey: "vhHostsHelp", requiredKey: "notfoundHostsRequired", onChange: () => { changed(); notFoundAutoCertificate?.refresh(); } });
|
||||||
listenerChoices(item.frontend?.listener_ids || []); certificateChoices(item.certificate_id);
|
listenerChoices(item.frontend?.listener_ids || []); certificateChoices(item.certificate_id);
|
||||||
|
notFoundAutoCertificate = window.rustProxyAutoCertificate.attach($("notfound-certificate"), { auto: !editing, hosts: () => { try { return readHosts(); } catch { return []; } }, certificates: () => envelope?.config.tls?.certificates || [] }); notFoundAutoCertificate.refresh();
|
||||||
$("notfound-mode").value = item.page?.kind || "welcome"; populateStatuses(item.page?.status ?? 404); $("notfound-html").value = item.page?.html || ""; syncMode(); dialog.showModal();
|
$("notfound-mode").value = item.page?.kind || "welcome"; populateStatuses(item.page?.status ?? 404); $("notfound-html").value = item.page?.html || ""; syncMode(); dialog.showModal();
|
||||||
}
|
}
|
||||||
function suspendDraft() {
|
function suspendDraft() {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
const form = $("redirect-form"), dialog = $("redirect-dialog"), list = $("redirect-list"), rules = $("redirect-rules");
|
const form = $("redirect-form"), dialog = $("redirect-dialog"), list = $("redirect-list"), rules = $("redirect-rules");
|
||||||
if (!form || !dialog || !list || !rules) return;
|
if (!form || !dialog || !list || !rules) return;
|
||||||
const sortColumns = ["id", "name", "hostname", "status", "target", "rules", "listeners", "certificate"];
|
const sortColumns = ["id", "name", "hostname", "status", "target", "rules", "listeners", "certificate"];
|
||||||
let editing = null, revision = null, dirty = false, readRedirectBindings = () => [], readRedirectHosts = () => [], listPrefs = { sort: "id", descending: false };
|
let redirectAutoCertificate = null, editing = null, revision = null, dirty = false, readRedirectBindings = () => [], readRedirectHosts = () => [], listPrefs = { sort: "id", descending: false };
|
||||||
function normalizeListPrefs(preferences) { return { sort: sortColumns.includes(preferences?.redirect_list_sort) ? preferences.redirect_list_sort : "id", descending: preferences?.redirect_list_descending === true }; }
|
function normalizeListPrefs(preferences) { return { sort: sortColumns.includes(preferences?.redirect_list_sort) ? preferences.redirect_list_sort : "id", descending: preferences?.redirect_list_descending === true }; }
|
||||||
function syncSortDirection() { const control = $("redirect-sort-direction"); if (!control) return; control.textContent = listPrefs.descending ? "↓" : "↑"; control.setAttribute("aria-label", t(listPrefs.descending ? "backendSortDescending" : "backendSortAscending")); }
|
function syncSortDirection() { const control = $("redirect-sort-direction"); if (!control) return; control.textContent = listPrefs.descending ? "↓" : "↑"; control.setAttribute("aria-label", t(listPrefs.descending ? "backendSortDescending" : "backendSortAscending")); }
|
||||||
function applyPreferences(preferences) { listPrefs = normalizeListPrefs(preferences); if ($("redirect-sort")) $("redirect-sort").value = listPrefs.sort; syncSortDirection(); render(); }
|
function applyPreferences(preferences) { listPrefs = normalizeListPrefs(preferences); if ($("redirect-sort")) $("redirect-sort").value = listPrefs.sort; syncSortDirection(); render(); }
|
||||||
@@ -71,9 +71,10 @@
|
|||||||
$("redirect-id").value = item.id || ""; $("redirect-id").disabled = Boolean(editing);
|
$("redirect-id").value = item.id || ""; $("redirect-id").disabled = Boolean(editing);
|
||||||
$("redirect-name").value = item.name || "";
|
$("redirect-name").value = item.name || "";
|
||||||
window.rustProxyAutoId.attach($("redirect-id"), { elements: [$("redirect-name")], taken: () => (envelope?.config.redirects || []).map(value => value.id) });
|
window.rustProxyAutoId.attach($("redirect-id"), { elements: [$("redirect-name")], taken: () => (envelope?.config.redirects || []).map(value => value.id) });
|
||||||
const hostHolder = $("redirect-hosts-editor"); hostHolder.replaceChildren(); readRedirectHosts = window.rustProxyIntegrations.hostnames(hostHolder, item.frontend?.hosts || [], { labelKey: "redirectHosts", helpKey: "vhHostsHelp", requiredKey: "redirectHostsRequired", onChange: changed });
|
const hostHolder = $("redirect-hosts-editor"); hostHolder.replaceChildren(); readRedirectHosts = window.rustProxyIntegrations.hostnames(hostHolder, item.frontend?.hosts || [], { labelKey: "redirectHosts", helpKey: "vhHostsHelp", requiredKey: "redirectHostsRequired", onChange: () => { changed(); redirectAutoCertificate?.refresh(); } });
|
||||||
$("redirect-enabled").checked = item.enabled !== false; syncEnabledControl(); $("redirect-http2").checked = item.http2_enabled !== false; $("redirect-http3").checked = item.http3_enabled !== false;
|
$("redirect-enabled").checked = item.enabled !== false; syncEnabledControl(); $("redirect-http2").checked = item.http2_enabled !== false; $("redirect-http3").checked = item.http3_enabled !== false;
|
||||||
listenerChoices(item.frontend?.listener_ids || []); certificateChoices(item.certificate_id);
|
listenerChoices(item.frontend?.listener_ids || []); certificateChoices(item.certificate_id);
|
||||||
|
redirectAutoCertificate = window.rustProxyAutoCertificate.attach($("redirect-certificate"), { auto: !editing, hosts: () => { try { return readRedirectHosts(); } catch { return []; } }, certificates: () => envelope?.config.tls?.certificates || [] }); redirectAutoCertificate.refresh();
|
||||||
rules.replaceChildren(); for (const [i, rule] of (item.rules?.length ? item.rules : defaults().rules).entries()) addRule(rule, i);
|
rules.replaceChildren(); for (const [i, rule] of (item.rules?.length ? item.rules : defaults().rules).entries()) addRule(rule, i);
|
||||||
dialog.showModal();
|
dialog.showModal();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ function load(value = defaults(), migrationIds = [], show = true) {
|
|||||||
container.replaceChildren(); $("vhost-editing").textContent = t(editing ? "vhEditLabel" : "vhNewLabel");
|
container.replaceChildren(); $("vhost-editing").textContent = t(editing ? "vhEditLabel" : "vhNewLabel");
|
||||||
let g = group("vhEditor"); const basicFields = subsection(g, "vhGeneralDetailsSection");
|
let g = group("vhEditor"); const basicFields = subsection(g, "vhGeneralDetailsSection");
|
||||||
const vhostIdInput = field(basicFields, "id", "vhId", value.id, "text", { required: true, maxLength: 64, pattern: "[A-Za-z0-9_-]{1,64}" }); if (editing) note(basicFields, "vhIdRenameHelp");
|
const vhostIdInput = field(basicFields, "id", "vhId", value.id, "text", { required: true, maxLength: 64, pattern: "[A-Za-z0-9_-]{1,64}" }); if (editing) note(basicFields, "vhIdRenameHelp");
|
||||||
let refreshCanonical = () => { }, vhostAutoId = null;
|
let refreshCanonical = () => { }, vhostAutoId = null, vhostAutoCertificate = null;
|
||||||
vhostAutoId = window.rustProxyAutoId.attach(vhostIdInput, { text: () => lines(read("hosts")?.value || "")[0] || "", taken: () => (envelope?.config.vhosts || []).map(item => item.id), resettable: !editing });
|
vhostAutoId = window.rustProxyAutoId.attach(vhostIdInput, { text: () => lines(read("hosts")?.value || "")[0] || "", taken: () => (envelope?.config.vhosts || []).map(item => item.id), resettable: !editing });
|
||||||
const enabledControl = field(basicFields, "enabled", "vhEnabled", value.enabled !== false, "checkbox");
|
const enabledControl = field(basicFields, "enabled", "vhEnabled", value.enabled !== false, "checkbox");
|
||||||
window.rustProxyEnableControl(enabledControl, "vhEnableHint");
|
window.rustProxyEnableControl(enabledControl, "vhEnableHint");
|
||||||
@@ -89,7 +89,7 @@ function load(value = defaults(), migrationIds = [], show = true) {
|
|||||||
const websocketLegacy = field(websocketFields, "websocket-legacy-support", "vhWebsocketLegacySupport", value.websocket_legacy_support === true, "checkbox");
|
const websocketLegacy = field(websocketFields, "websocket-legacy-support", "vhWebsocketLegacySupport", value.websocket_legacy_support === true, "checkbox");
|
||||||
note(websocketFields, "vhWebsocketLegacySupportHelp");
|
note(websocketFields, "vhWebsocketLegacySupportHelp");
|
||||||
g = group("vhFrontends");
|
g = group("vhFrontends");
|
||||||
readHosts = hostTagEditor(g, value.frontend?.hosts || [], hosts => { refreshCanonical(hosts); vhostAutoId?.refresh(); });
|
readHosts = hostTagEditor(g, value.frontend?.hosts || [], hosts => { refreshCanonical(hosts); vhostAutoId?.refresh(); vhostAutoCertificate?.refresh(hosts); });
|
||||||
if (!editing) g.lastElementChild?.after(vhostIdInput.closest("label"));
|
if (!editing) g.lastElementChild?.after(vhostIdInput.closest("label"));
|
||||||
const bindingControl = window.rustProxyIntegrations.bindings(g, value.frontend?.listener_ids || [], !editing); readBindings = bindingControl.read;
|
const bindingControl = window.rustProxyIntegrations.bindings(g, value.frontend?.listener_ids || [], !editing); readBindings = bindingControl.read;
|
||||||
note(g, "listenerDefaultPortsHint");
|
note(g, "listenerDefaultPortsHint");
|
||||||
@@ -350,6 +350,7 @@ function load(value = defaults(), migrationIds = [], show = true) {
|
|||||||
const certificateRow = el("div", undefined, "vh-wide vh-certificate-select-row"); g.append(certificateRow);
|
const certificateRow = el("div", undefined, "vh-wide vh-certificate-select-row"); g.append(certificateRow);
|
||||||
const selector = field(certificateRow, "certificate-id", "vhCertificate", value.certificate_id || "", "select");
|
const selector = field(certificateRow, "certificate-id", "vhCertificate", value.certificate_id || "", "select");
|
||||||
const fillCertificates = () => { const selected = selector.value || value.certificate_id || ""; const inherit = text("option", "vhCertificateDefault"); inherit.value = ""; selector.replaceChildren(inherit, ...[...(envelope?.config.tls?.certificates || []), ...stagedCertificates].map(c => { const o = el("option", c.id); o.value = c.id; return o; })); selector.value = selected; }; fillCertificates();
|
const fillCertificates = () => { const selected = selector.value || value.certificate_id || ""; const inherit = text("option", "vhCertificateDefault"); inherit.value = ""; selector.replaceChildren(inherit, ...[...(envelope?.config.tls?.certificates || []), ...stagedCertificates].map(c => { const o = el("option", c.id); o.value = c.id; return o; })); selector.value = selected; }; fillCertificates();
|
||||||
|
vhostAutoCertificate = window.rustProxyAutoCertificate.attach(selector, { auto: !editing, anchor: certificateRow, hosts: () => { try { return readHosts(); } catch { return []; } }, certificates: () => [...(envelope?.config.tls?.certificates || []), ...stagedCertificates] }); vhostAutoCertificate.refresh();
|
||||||
certificateRow.append(button("certManage", async () => { if (!(await closeEditor())) return; setPanel("tls"); }));
|
certificateRow.append(button("certManage", async () => { if (!(await closeEditor())) return; setPanel("tls"); }));
|
||||||
note(g, "certSelectHint");
|
note(g, "certSelectHint");
|
||||||
const mismatch = field(g, "allow-certificate-mismatch", "vhCertificateMismatchForce", value.allow_certificate_mismatch === true, "checkbox");
|
const mismatch = field(g, "allow-certificate-mismatch", "vhCertificateMismatchForce", value.allow_certificate_mismatch === true, "checkbox");
|
||||||
|
|||||||
+23
-10
@@ -150,28 +150,35 @@ pub fn compile_reusing(
|
|||||||
type LocalHostBuild = (
|
type LocalHostBuild = (
|
||||||
HashMap<String, Vec<Arc<crate::redirect::CompiledHost>>>,
|
HashMap<String, Vec<Arc<crate::redirect::CompiledHost>>>,
|
||||||
HashMap<String, Vec<Arc<crate::not_found::CompiledHost>>>,
|
HashMap<String, Vec<Arc<crate::not_found::CompiledHost>>>,
|
||||||
HashMap<String, Vec<crate::vhost::Listener>>,
|
HashMap<String, Vec<(String, crate::vhost::Listener)>>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn compile_local_hosts(config: &Config) -> Result<LocalHostBuild> {
|
fn compile_local_hosts(config: &Config) -> Result<LocalHostBuild> {
|
||||||
let mut redirects: HashMap<String, Vec<Arc<crate::redirect::CompiledHost>>> = HashMap::new();
|
let mut redirects: HashMap<String, Vec<Arc<crate::redirect::CompiledHost>>> = HashMap::new();
|
||||||
let mut not_found_hosts: HashMap<String, Vec<Arc<crate::not_found::CompiledHost>>> =
|
let mut not_found_hosts: HashMap<String, Vec<Arc<crate::not_found::CompiledHost>>> =
|
||||||
HashMap::new();
|
HashMap::new();
|
||||||
let mut claimed_hosts: HashMap<String, Vec<crate::vhost::Listener>> = HashMap::new();
|
let mut claimed_hosts: HashMap<String, Vec<(String, crate::vhost::Listener)>> =
|
||||||
|
HashMap::new();
|
||||||
for redirect in &config.redirects {
|
for redirect in &config.redirects {
|
||||||
let bindings = redirect.frontend.resolved(&config.listeners)?;
|
let bindings = redirect.frontend.resolved(&config.listeners)?;
|
||||||
for name in &redirect.frontend.hosts {
|
for name in &redirect.frontend.hosts {
|
||||||
let claimed = claimed_hosts.entry(name.clone()).or_default();
|
let claimed = claimed_hosts.entry(name.clone()).or_default();
|
||||||
for a in claimed.iter() {
|
for (owner, a) in claimed.iter() {
|
||||||
for b in &bindings {
|
for b in &bindings {
|
||||||
ensure!(
|
ensure!(
|
||||||
!crate::vhost::socket_overlap(a.address, b.address),
|
!crate::vhost::socket_overlap(a.address, b.address),
|
||||||
"overlapping frontend bindings for hostname {}",
|
"overlapping frontend bindings for hostname {} (already used by {} on {})",
|
||||||
name
|
name,
|
||||||
|
owner,
|
||||||
|
a.address
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
claimed.extend(bindings.iter().copied());
|
claimed.extend(
|
||||||
|
bindings
|
||||||
|
.iter()
|
||||||
|
.map(|binding| (format!("redirect {}", redirect.id), *binding)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if redirect.enabled {
|
if redirect.enabled {
|
||||||
let compiled = Arc::new(crate::redirect::compile(redirect, &config.listeners)?);
|
let compiled = Arc::new(crate::redirect::compile(redirect, &config.listeners)?);
|
||||||
@@ -187,16 +194,22 @@ fn compile_local_hosts(config: &Config) -> Result<LocalHostBuild> {
|
|||||||
let bindings = host.frontend.resolved(&config.listeners)?;
|
let bindings = host.frontend.resolved(&config.listeners)?;
|
||||||
for name in &host.frontend.hosts {
|
for name in &host.frontend.hosts {
|
||||||
let claimed = claimed_hosts.entry(name.clone()).or_default();
|
let claimed = claimed_hosts.entry(name.clone()).or_default();
|
||||||
for a in claimed.iter() {
|
for (owner, a) in claimed.iter() {
|
||||||
for b in &bindings {
|
for b in &bindings {
|
||||||
ensure!(
|
ensure!(
|
||||||
!crate::vhost::socket_overlap(a.address, b.address),
|
!crate::vhost::socket_overlap(a.address, b.address),
|
||||||
"overlapping frontend bindings for hostname {}",
|
"overlapping frontend bindings for hostname {} (already used by {} on {})",
|
||||||
name
|
name,
|
||||||
|
owner,
|
||||||
|
a.address
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
claimed.extend(bindings.iter().copied());
|
claimed.extend(
|
||||||
|
bindings
|
||||||
|
.iter()
|
||||||
|
.map(|binding| (format!("404 host {}", host.id), *binding)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if host.enabled {
|
if host.enabled {
|
||||||
let compiled = Arc::new(crate::not_found::compile(host, &config.listeners)?);
|
let compiled = Arc::new(crate::not_found::compile(host, &config.listeners)?);
|
||||||
|
|||||||
+21
-8
@@ -65,7 +65,8 @@ pub fn compile_with_active(
|
|||||||
php_profiles
|
php_profiles
|
||||||
.insert(profile.id.clone(), profile.php.clone())
|
.insert(profile.id.clone(), profile.php.clone())
|
||||||
.is_none(),
|
.is_none(),
|
||||||
"duplicate PHP-FPM profile id"
|
"duplicate PHP-FPM profile id {:?}: every profile needs a unique ID",
|
||||||
|
profile.id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ensure!(
|
ensure!(
|
||||||
@@ -120,7 +121,8 @@ pub fn compile_with_active(
|
|||||||
);
|
);
|
||||||
ensure!(
|
ensure!(
|
||||||
web_services.insert(service.id.clone(), compiled).is_none(),
|
web_services.insert(service.id.clone(), compiled).is_none(),
|
||||||
"duplicate Web Service id"
|
"duplicate Web Service id {:?}: every Web Service needs a unique ID",
|
||||||
|
service.id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ensure!(config.vhosts.len() <= 64, "too many vhosts (max 64)");
|
ensure!(config.vhosts.len() <= 64, "too many vhosts (max 64)");
|
||||||
@@ -145,7 +147,11 @@ pub fn compile_with_active(
|
|||||||
validate_source(&route.source)?;
|
validate_source(&route.source)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ensure!(vhost_ids.insert(host.id.clone()), "duplicate vhost id");
|
ensure!(
|
||||||
|
vhost_ids.insert(host.id.clone()),
|
||||||
|
"duplicate vhost id {:?}: every vhost needs a unique ID",
|
||||||
|
host.id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ensure!(
|
ensure!(
|
||||||
config.redirects.len() <= 64,
|
config.redirects.len() <= 64,
|
||||||
@@ -158,7 +164,8 @@ pub fn compile_with_active(
|
|||||||
.with_context(|| format!("redirect {}", redirect.id))?;
|
.with_context(|| format!("redirect {}", redirect.id))?;
|
||||||
ensure!(
|
ensure!(
|
||||||
redirect_ids.insert(redirect.id.clone()),
|
redirect_ids.insert(redirect.id.clone()),
|
||||||
"duplicate redirect id"
|
"duplicate redirect id {:?}: every redirect needs a unique ID",
|
||||||
|
redirect.id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ensure!(
|
ensure!(
|
||||||
@@ -171,7 +178,8 @@ pub fn compile_with_active(
|
|||||||
.with_context(|| format!("404 host {}", host.id))?;
|
.with_context(|| format!("404 host {}", host.id))?;
|
||||||
ensure!(
|
ensure!(
|
||||||
not_found_ids.insert(host.id.clone()),
|
not_found_ids.insert(host.id.clone()),
|
||||||
"duplicate 404 host id"
|
"duplicate 404 host id {:?}: every 404 host needs a unique ID",
|
||||||
|
host.id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let effective_tls = crate::tls::for_all_frontends(
|
let effective_tls = crate::tls::for_all_frontends(
|
||||||
@@ -279,7 +287,11 @@ pub fn compile_with_active(
|
|||||||
let mut acl_profiles: HashMap<String, (Option<CompiledAcl>, crate::rate_limit::CountryAccess)> =
|
let mut acl_profiles: HashMap<String, (Option<CompiledAcl>, crate::rate_limit::CountryAccess)> =
|
||||||
HashMap::new();
|
HashMap::new();
|
||||||
for profile in &mut config.acl_profiles {
|
for profile in &mut config.acl_profiles {
|
||||||
ensure!(valid_id(&profile.id), "invalid ACL profile id");
|
ensure!(
|
||||||
|
valid_id(&profile.id),
|
||||||
|
"invalid ACL profile id {:?}: use 1-64 letters, digits, '-' or '_'",
|
||||||
|
profile.id
|
||||||
|
);
|
||||||
ensure!(
|
ensure!(
|
||||||
!profile.name.trim().is_empty()
|
!profile.name.trim().is_empty()
|
||||||
&& profile.name.len() <= 96
|
&& profile.name.len() <= 96
|
||||||
@@ -293,7 +305,8 @@ pub fn compile_with_active(
|
|||||||
acl_profiles
|
acl_profiles
|
||||||
.insert(profile.id.clone(), (acl, profile.country_access.clone()))
|
.insert(profile.id.clone(), (acl, profile.country_access.clone()))
|
||||||
.is_none(),
|
.is_none(),
|
||||||
"duplicate ACL profile id"
|
"duplicate ACL profile id {:?}: every ACL profile needs a unique ID",
|
||||||
|
profile.id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
crate::acl::dynamic::configured_hostnames(&config)?;
|
crate::acl::dynamic::configured_hostnames(&config)?;
|
||||||
@@ -380,7 +393,7 @@ fn normalize_prefix(prefix: &mut String) -> Result<()> {
|
|||||||
&& !prefix.contains('?')
|
&& !prefix.contains('?')
|
||||||
&& !prefix.contains('#')
|
&& !prefix.contains('#')
|
||||||
&& !prefix.bytes().any(|b| b <= 32 || b == 127),
|
&& !prefix.bytes().any(|b| b <= 32 || b == 127),
|
||||||
"invalid path prefix"
|
"invalid path prefix: it must start with '/', be at most 512 bytes and contain no '?', '#', spaces or control characters"
|
||||||
);
|
);
|
||||||
if prefix.len() > 1 {
|
if prefix.len() > 1 {
|
||||||
*prefix = prefix.trim_end_matches('/').to_owned();
|
*prefix = prefix.trim_end_matches('/').to_owned();
|
||||||
|
|||||||
+25
-10
@@ -79,16 +79,22 @@ fn compile_routing(
|
|||||||
);
|
);
|
||||||
for name in &routing_hosts {
|
for name in &routing_hosts {
|
||||||
let claimed = claimed_hosts.entry(name.clone()).or_default();
|
let claimed = claimed_hosts.entry(name.clone()).or_default();
|
||||||
for a in claimed.iter() {
|
for (owner, a) in claimed.iter() {
|
||||||
for b in &host_bindings {
|
for b in &host_bindings {
|
||||||
ensure!(
|
ensure!(
|
||||||
!crate::vhost::socket_overlap(a.address, b.address),
|
!crate::vhost::socket_overlap(a.address, b.address),
|
||||||
"overlapping frontend bindings for hostname {}",
|
"overlapping frontend bindings for hostname {} (already used by {} on {})",
|
||||||
name
|
name,
|
||||||
|
owner,
|
||||||
|
a.address
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
claimed.extend(host_bindings.iter().copied());
|
claimed.extend(
|
||||||
|
host_bindings
|
||||||
|
.iter()
|
||||||
|
.map(|binding| (format!("vhost {}", host.id), *binding)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let needs_proxy_pool = host.source.is_reverse_proxy()
|
let needs_proxy_pool = host.source.is_reverse_proxy()
|
||||||
|| host.routes.iter().any(|route| {
|
|| host.routes.iter().any(|route| {
|
||||||
@@ -323,7 +329,8 @@ fn compile_routing(
|
|||||||
for route in &mut host.routes {
|
for route in &mut host.routes {
|
||||||
ensure!(
|
ensure!(
|
||||||
valid_id(&route.id) && path_ids.insert(route.id.clone()),
|
valid_id(&route.id) && path_ids.insert(route.id.clone()),
|
||||||
"invalid/duplicate vhost path id"
|
"location ID {:?} is invalid or used twice in this vhost (use 1-64 letters, digits, '-' or '_', unique per vhost)",
|
||||||
|
route.id
|
||||||
);
|
);
|
||||||
let path_regex = match route.match_type {
|
let path_regex = match route.match_type {
|
||||||
crate::vhost::PathMatch::Regex | crate::vhost::PathMatch::RegexInsensitive => {
|
crate::vhost::PathMatch::Regex | crate::vhost::PathMatch::RegexInsensitive => {
|
||||||
@@ -331,7 +338,8 @@ fn compile_routing(
|
|||||||
!route.path_prefix.is_empty()
|
!route.path_prefix.is_empty()
|
||||||
&& route.path_prefix.len() <= 1024
|
&& route.path_prefix.len() <= 1024
|
||||||
&& !route.path_prefix.chars().any(char::is_control),
|
&& !route.path_prefix.chars().any(char::is_control),
|
||||||
"invalid vhost location regex"
|
"location {}: the regular expression must be 1-1024 characters without control characters",
|
||||||
|
route.id
|
||||||
);
|
);
|
||||||
let mut builder = regex::RegexBuilder::new(&route.path_prefix);
|
let mut builder = regex::RegexBuilder::new(&route.path_prefix);
|
||||||
builder
|
builder
|
||||||
@@ -340,17 +348,23 @@ fn compile_routing(
|
|||||||
)
|
)
|
||||||
.size_limit(2 * 1024 * 1024)
|
.size_limit(2 * 1024 * 1024)
|
||||||
.dfa_size_limit(2 * 1024 * 1024);
|
.dfa_size_limit(2 * 1024 * 1024);
|
||||||
Some(builder.build().context("invalid vhost location regex")?)
|
Some(builder.build().with_context(|| {
|
||||||
|
format!(
|
||||||
|
"location {}: invalid or too complex regular expression",
|
||||||
|
route.id
|
||||||
|
)
|
||||||
|
})?)
|
||||||
}
|
}
|
||||||
crate::vhost::PathMatch::Exact => {
|
crate::vhost::PathMatch::Exact => {
|
||||||
ensure!(
|
ensure!(
|
||||||
!route.path_prefix.contains('?')
|
!route.path_prefix.contains('?')
|
||||||
&& !route.path_prefix.contains('#')
|
&& !route.path_prefix.contains('#')
|
||||||
&& !route.path_prefix.bytes().any(|b| b <= 32 || b == 127),
|
&& !route.path_prefix.bytes().any(|b| b <= 32 || b == 127),
|
||||||
"invalid exact location path"
|
"location {}: an exact path must not contain '?', '#', spaces or control characters",
|
||||||
|
route.id
|
||||||
);
|
);
|
||||||
route.path_prefix = crate::acl::routing_path(&route.path_prefix)
|
route.path_prefix = crate::acl::routing_path(&route.path_prefix)
|
||||||
.context("invalid exact location path")?;
|
.with_context(|| format!("location {}: invalid exact path", route.id))?;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
crate::vhost::PathMatch::Prefix | crate::vhost::PathMatch::PrefixPriority => {
|
crate::vhost::PathMatch::Prefix | crate::vhost::PathMatch::PrefixPriority => {
|
||||||
@@ -361,7 +375,8 @@ fn compile_routing(
|
|||||||
if !route.internal {
|
if !route.internal {
|
||||||
ensure!(
|
ensure!(
|
||||||
path_bindings.insert((route.match_type, route.path_prefix.clone())),
|
path_bindings.insert((route.match_type, route.path_prefix.clone())),
|
||||||
"duplicate vhost location matcher"
|
"location {}: another location already uses the same path and match type",
|
||||||
|
route.id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
validate_route_rewrite(route, path_regex.as_ref())?;
|
validate_route_rewrite(route, path_regex.as_ref())?;
|
||||||
|
|||||||
+10
-2
@@ -37,7 +37,11 @@ fn default_page() -> crate::pages::Page {
|
|||||||
|
|
||||||
impl Host {
|
impl Host {
|
||||||
pub fn validate(&mut self) -> Result<()> {
|
pub fn validate(&mut self) -> Result<()> {
|
||||||
ensure!(crate::config::valid_id(&self.id), "invalid 404 host id");
|
ensure!(
|
||||||
|
crate::config::valid_id(&self.id),
|
||||||
|
"invalid 404 host id {:?}: use 1-64 letters, digits, '-' or '_'",
|
||||||
|
self.id
|
||||||
|
);
|
||||||
if self.name.trim().is_empty() {
|
if self.name.trim().is_empty() {
|
||||||
self.name = self.id.clone();
|
self.name = self.id.clone();
|
||||||
}
|
}
|
||||||
@@ -55,7 +59,11 @@ impl Host {
|
|||||||
let mut hosts = std::collections::HashSet::new();
|
let mut hosts = std::collections::HashSet::new();
|
||||||
for host in &mut self.frontend.hosts {
|
for host in &mut self.frontend.hosts {
|
||||||
*host = crate::config::normalize_host_pattern(host)?;
|
*host = crate::config::normalize_host_pattern(host)?;
|
||||||
ensure!(hosts.insert(host.clone()), "duplicate 404 hostname");
|
ensure!(
|
||||||
|
hosts.insert(host.clone()),
|
||||||
|
"hostname {} is listed twice in this 404 host",
|
||||||
|
host
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ensure!(
|
ensure!(
|
||||||
!self.frontend.listener_ids.is_empty() && self.frontend.listener_ids.len() <= 16,
|
!self.frontend.listener_ids.is_empty() && self.frontend.listener_ids.len() <= 16,
|
||||||
|
|||||||
+12
-4
@@ -127,7 +127,11 @@ pub struct Host {
|
|||||||
}
|
}
|
||||||
impl Host {
|
impl Host {
|
||||||
pub fn validate(&mut self) -> Result<()> {
|
pub fn validate(&mut self) -> Result<()> {
|
||||||
ensure!(crate::config::valid_id(&self.id), "invalid redirect id");
|
ensure!(
|
||||||
|
crate::config::valid_id(&self.id),
|
||||||
|
"invalid redirect id {:?}: use 1-64 letters, digits, '-' or '_'",
|
||||||
|
self.id
|
||||||
|
);
|
||||||
if self.name.is_empty() {
|
if self.name.is_empty() {
|
||||||
self.name = self.id.clone();
|
self.name = self.id.clone();
|
||||||
}
|
}
|
||||||
@@ -140,16 +144,20 @@ impl Host {
|
|||||||
);
|
);
|
||||||
ensure!(
|
ensure!(
|
||||||
!self.frontend.hosts.is_empty(),
|
!self.frontend.hosts.is_empty(),
|
||||||
"redirect requires at least one hostname"
|
"redirect requires at least one hostname (for example old.example.com)"
|
||||||
);
|
);
|
||||||
let mut hosts = std::collections::HashSet::new();
|
let mut hosts = std::collections::HashSet::new();
|
||||||
for host in &mut self.frontend.hosts {
|
for host in &mut self.frontend.hosts {
|
||||||
*host = crate::config::normalize_host_pattern(host)?;
|
*host = crate::config::normalize_host_pattern(host)?;
|
||||||
ensure!(hosts.insert(host.clone()), "duplicate redirect hostname");
|
ensure!(
|
||||||
|
hosts.insert(host.clone()),
|
||||||
|
"hostname {} is listed twice in this redirect",
|
||||||
|
host
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ensure!(
|
ensure!(
|
||||||
!self.frontend.listener_ids.is_empty() && self.frontend.listener_ids.len() <= 16,
|
!self.frontend.listener_ids.is_empty() && self.frontend.listener_ids.len() <= 16,
|
||||||
"redirect requires 1..16 named listeners"
|
"select between 1 and 16 listeners for this redirect"
|
||||||
);
|
);
|
||||||
if self.rules.is_empty() {
|
if self.rules.is_empty() {
|
||||||
self.rules.push(Rule::default());
|
self.rules.push(Rule::default());
|
||||||
|
|||||||
+14
-5
@@ -46,7 +46,11 @@ impl PathRoute {
|
|||||||
}
|
}
|
||||||
impl Vhost {
|
impl Vhost {
|
||||||
pub fn validate(&mut self) -> Result<()> {
|
pub fn validate(&mut self) -> Result<()> {
|
||||||
ensure!(crate::config::valid_id(&self.id), "invalid vhost id");
|
ensure!(
|
||||||
|
crate::config::valid_id(&self.id),
|
||||||
|
"invalid vhost id {:?}: use 1-64 letters, digits, '-' or '_'",
|
||||||
|
self.id
|
||||||
|
);
|
||||||
ensure!(
|
ensure!(
|
||||||
!self.websocket_legacy_support || self.websockets,
|
!self.websocket_legacy_support || self.websockets,
|
||||||
"legacy WebSocket compatibility requires WebSocket support to be enabled"
|
"legacy WebSocket compatibility requires WebSocket support to be enabled"
|
||||||
@@ -69,12 +73,16 @@ impl Vhost {
|
|||||||
);
|
);
|
||||||
ensure!(
|
ensure!(
|
||||||
!self.frontend.hosts.is_empty(),
|
!self.frontend.hosts.is_empty(),
|
||||||
"vhost requires at least one hostname"
|
"vhost requires at least one hostname (for example app.example.com) in the Frontend section"
|
||||||
);
|
);
|
||||||
let mut hosts = std::collections::HashSet::new();
|
let mut hosts = std::collections::HashSet::new();
|
||||||
for host in &mut self.frontend.hosts {
|
for host in &mut self.frontend.hosts {
|
||||||
*host = crate::config::normalize_host_pattern(host)?;
|
*host = crate::config::normalize_host_pattern(host)?;
|
||||||
ensure!(hosts.insert(host.clone()), "duplicate vhost hostname");
|
ensure!(
|
||||||
|
hosts.insert(host.clone()),
|
||||||
|
"hostname {} is listed twice in this vhost",
|
||||||
|
host
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if let Some(target) = &mut self.www_redirect_target {
|
if let Some(target) = &mut self.www_redirect_target {
|
||||||
*target = crate::config::normalize_host_pattern(target)?;
|
*target = crate::config::normalize_host_pattern(target)?;
|
||||||
@@ -101,7 +109,7 @@ impl Vhost {
|
|||||||
self.content_type_policy.validate()?;
|
self.content_type_policy.validate()?;
|
||||||
ensure!(
|
ensure!(
|
||||||
!self.frontend.listener_ids.is_empty(),
|
!self.frontend.listener_ids.is_empty(),
|
||||||
"vhost requires at least one named listener"
|
"select at least one listener for this vhost in the Frontend section"
|
||||||
);
|
);
|
||||||
ensure!(
|
ensure!(
|
||||||
self.frontend.listener_ids.len() <= 16,
|
self.frontend.listener_ids.len() <= 16,
|
||||||
@@ -150,7 +158,8 @@ impl Vhost {
|
|||||||
for route in &mut self.routes {
|
for route in &mut self.routes {
|
||||||
ensure!(
|
ensure!(
|
||||||
crate::config::valid_id(&route.id) && route_ids.insert(route.id.clone()),
|
crate::config::valid_id(&route.id) && route_ids.insert(route.id.clone()),
|
||||||
"invalid/duplicate vhost path id"
|
"location ID {:?} is invalid or used twice in this vhost (use 1-64 letters, digits, '-' or '_', unique per vhost)",
|
||||||
|
route.id
|
||||||
);
|
);
|
||||||
route.source.validate()?;
|
route.source.validate()?;
|
||||||
ensure!(
|
ensure!(
|
||||||
|
|||||||
@@ -51,5 +51,5 @@ const events = openapi.paths["/api/events"].get;
|
|||||||
const logsFlag = (events.parameters || []).find(parameter => parameter.name === "logs");
|
const logsFlag = (events.parameters || []).find(parameter => parameter.name === "logs");
|
||||||
assert.equal(logsFlag?.schema?.type, "boolean");
|
assert.equal(logsFlag?.schema?.type, "boolean");
|
||||||
assert.equal(logsFlag?.schema?.default, true);
|
assert.equal(logsFlag?.schema?.default, true);
|
||||||
assert.equal(openapi.info.version, "0.36.4");
|
assert.equal(openapi.info.version, "0.36.5");
|
||||||
console.log("Panel refresh/API contract checks: OK");
|
console.log("Panel refresh/API contract checks: OK");
|
||||||
Reference in new issue
Block a user