v0.27.0-hotfix
This commit is contained in:
1 parent
762eb9e28b
commit
39238fdf53
17 files changed
+74
-67
No files matched your search
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
- Enable downstream response compression by default for zstd, Brotli and gzip; keep deflate opt-in. Client q-values remain authoritative and equal-quality encodings use `zstd -> br -> gzip -> deflate` priority. Existing `Content-Encoding` is passed through unchanged.
|
- Enable downstream response compression by default for zstd, Brotli and gzip; keep deflate opt-in. Client q-values remain authoritative and equal-quality encodings use `zstd -> br -> gzip -> deflate` priority. Existing `Content-Encoding` is passed through unchanged.
|
||||||
- Compress eligible authenticated/cookie/private/no-store responses instead of broadly excluding them. Explicit `no-transform`, ranges, SSE, upgrades and already encoded responses remain uncompressed by RustProxy.
|
- Compress eligible authenticated/cookie/private/no-store responses instead of broadly excluding them. Explicit `no-transform`, ranges, SSE, upgrades and already encoded responses remain uncompressed by RustProxy.
|
||||||
- Add inherit/enable/disable dynamic-compression controls plus per-scope zstd/Brotli/gzip/deflate filters to ordinary vhosts, generated Docker vhosts and Web Server services. Global Response settings remain the hard codec ceiling and own the minimum size. When a scope is explicitly Disabled, codec inheritance controls disappear and are disabled while their saved values are retained for later re-enable.
|
- Add inherit/enable/disable dynamic-compression controls plus per-scope zstd/Brotli/gzip/deflate filters to ordinary vhosts and Web Server services. Docker vhosts use a deliberately simpler single Compression checkbox and always use the codec set/priorities from global Response settings. Global Response settings remain the hard codec ceiling and own the minimum size.
|
||||||
- Keep every explicitly published Docker hostname routed until it is explicitly unpublished. Missing services return `503 Service Unavailable`; temporary agent failures reuse the last successful inventory when present, and returning services are reattached automatically.
|
- Keep every explicitly published Docker hostname routed until it is explicitly unpublished. Missing services return `503 Service Unavailable`; temporary agent failures reuse the last successful inventory when present, and returning services are reattached automatically.
|
||||||
- Fix HOT/COLD cache progress meters so their configured-limit fill is visible in Chromium/WebKit and Firefox.
|
- Fix HOT/COLD cache progress meters so their configured-limit fill is visible in Chromium/WebKit and Firefox.
|
||||||
- Make fresh installations emit `Server: RustProxy` by default while preserving existing saved/legacy behavior.
|
- Make fresh installations emit `Server: RustProxy` by default while preserving existing saved/legacy behavior.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Named HTTP/HTTPS listener bind addresses use the same chip-style editor as vhost
|
|||||||
|
|
||||||
- Enable downstream compression by default with `zstd`, Brotli and gzip codecs; deflate remains opt-in. Honor client `q` values first and use deterministic `zstd -> br -> gzip -> deflate` server preference when quality is equal. Existing `Content-Encoding` is never recompressed.
|
- Enable downstream compression by default with `zstd`, Brotli and gzip codecs; deflate remains opt-in. Honor client `q` values first and use deterministic `zstd -> br -> gzip -> deflate` server preference when quality is equal. Existing `Content-Encoding` is never recompressed.
|
||||||
- Stop treating authentication/cookie/cache-privacy headers as blanket compression blockers. `Cookie`, `Authorization`, `Set-Cookie`, `private` and `no-store` may be compressed; `no-transform`, ranges, SSE, upgrades and already encoded responses remain excluded.
|
- Stop treating authentication/cookie/cache-privacy headers as blanket compression blockers. `Cookie`, `Authorization`, `Set-Cookie`, `private` and `no-store` may be compressed; `no-transform`, ranges, SSE, upgrades and already encoded responses remain excluded.
|
||||||
- Add dynamic compression inheritance/overrides to ordinary vhosts, generated Docker vhosts and Web Server services, including per-scope codec filters. Global Response settings remain the hard codec ceiling and own the minimum size. When a scope explicitly disables compression, its codec selectors are hidden/disabled without erasing the saved overrides.
|
- Add dynamic compression inheritance/overrides to ordinary vhosts and Web Server services, including per-scope codec filters. Docker vhosts intentionally expose only one Compression checkbox; their codec set and priority come from global Response settings. Global Response settings remain the hard codec ceiling and own the minimum size.
|
||||||
- Keep an explicitly published Docker vhost routed until the administrator unpublishes it. A missing container/service now keeps the hostname and returns `503 Service Unavailable`; an agent transport failure reuses the last successful inventory when available, and service return is reconciled automatically.
|
- Keep an explicitly published Docker vhost routed until the administrator unpublishes it. A missing container/service now keeps the hostname and returns `503 Service Unavailable`; an agent transport failure reuses the last successful inventory when available, and service return is reconciled automatically.
|
||||||
- Make `/cache` occupancy meters render their filled portion consistently in Chromium/WebKit and Firefox instead of relying only on native `accent-color`.
|
- Make `/cache` occupancy meters render their filled portion consistently in Chromium/WebKit and Firefox instead of relying only on native `accent-color`.
|
||||||
- Keep SQLite schema 8. New saved compression fields are additive/defaulted, so older 0.26.x documents continue to load. Fresh installations default the `Server` response header to exactly `RustProxy`.
|
- Keep SQLite schema 8. New saved compression fields are additive/defaulted, so older 0.26.x documents continue to load. Fresh installations default the `Server` response header to exactly `RustProxy`.
|
||||||
@@ -327,8 +327,9 @@ and gzip default ON while deflate defaults OFF, and equal client quality uses
|
|||||||
in `Content-Encoding` with `Vary: Accept-Encoding`. Existing `Content-Encoding`, ranges,
|
in `Content-Encoding` with `Vary: Accept-Encoding`. Existing `Content-Encoding`, ranges,
|
||||||
SSE, upgrades and `no-transform` are passed through without recompression. Cookie,
|
SSE, upgrades and `no-transform` are passed through without recompression. Cookie,
|
||||||
Authorization, Set-Cookie, private and no-store headers do not by themselves disable
|
Authorization, Set-Cookie, private and no-store headers do not by themselves disable
|
||||||
dynamic compression. Ordinary vhosts, Docker publications and Web Server services may
|
dynamic compression. Ordinary vhosts and Web Server services may inherit/enable/disable
|
||||||
inherit/enable/disable compression and individual codecs; explicitly disabling a scope
|
compression and individual codecs. Docker publications expose a single Compression on/off switch
|
||||||
|
and always use the globally enabled codec set; explicitly disabling a configurable scope
|
||||||
hides/disables its codec selectors in the dashboard while preserving their saved values.
|
hides/disables its codec selectors in the dashboard while preserving their saved values.
|
||||||
Strong ETags are weakened after transformation, and obsolete content digests are removed.
|
Strong ETags are weakened after transformation, and obsolete content digests are removed.
|
||||||
Server policy is applied after generic response rules. Protected framing/identity headers
|
Server policy is applied after generic response rules. Protected framing/identity headers
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ Current direction: 0.26.7 -> 0.27.0
|
|||||||
|
|
||||||
- [x] Enable zstd/Brotli/gzip downstream compression by default, keep deflate opt-in, honor client q-values and use deterministic `zstd -> br -> gzip -> deflate` tie priority.
|
- [x] Enable zstd/Brotli/gzip downstream compression by default, keep deflate opt-in, honor client q-values and use deterministic `zstd -> br -> gzip -> deflate` tie priority.
|
||||||
- [x] Allow authenticated/cookie/private/no-store responses to compress while retaining explicit no-transform/range/SSE/upgrade/existing-encoding exclusions.
|
- [x] Allow authenticated/cookie/private/no-store responses to compress while retaining explicit no-transform/range/SSE/upgrade/existing-encoding exclusions.
|
||||||
- [x] Add inherited dynamic-compression overrides for vhosts, Docker publications and Web Server services, including per-scope codec filters under the global codec ceiling; hide/disable codec controls while a scope is explicitly OFF without clearing saved overrides.
|
- [x] Add inherited dynamic-compression overrides and per-scope codec filters for ordinary vhosts and Web Server services under the global codec ceiling; keep Docker publications intentionally simple with one Compression on/off checkbox using the global codec set.
|
||||||
- [x] Default fresh installations to `Server: RustProxy` without rewriting existing saved policies.
|
- [x] Default fresh installations to `Server: RustProxy` without rewriting existing saved policies.
|
||||||
- [x] Remove Debian package-build metadata from this source tree; packaging is maintained separately at `rustproxy.linuxiarz.pl`.
|
- [x] Remove Debian package-build metadata from this source tree; packaging is maintained separately at `rustproxy.linuxiarz.pl`.
|
||||||
- [x] Keep published Docker hostnames materialized while a service is missing, return 503 until it returns, and reuse last-known inventory during temporary agent communication failures.
|
- [x] Keep published Docker hostnames materialized while a service is missing, return 503 until it returns, and reuse last-known inventory during temporary agent communication failures.
|
||||||
|
|||||||
+16
-16
@@ -2,12 +2,12 @@
|
|||||||
4140a2956264b44f259e6a37fc00ba02097bbe68b09296e04d3d243c1287129b .env.example
|
4140a2956264b44f259e6a37fc00ba02097bbe68b09296e04d3d243c1287129b .env.example
|
||||||
9e6356475bf587091bab72246ec9e325b498f7e48a6220e9a18baa50d0a385a6 .gitignore
|
9e6356475bf587091bab72246ec9e325b498f7e48a6220e9a18baa50d0a385a6 .gitignore
|
||||||
e2fd35a4ed8c601bab52efb6befbe6e0fc9718cc6616644f11f90d9dcee69db3 AGENTS.md
|
e2fd35a4ed8c601bab52efb6befbe6e0fc9718cc6616644f11f90d9dcee69db3 AGENTS.md
|
||||||
da0b500b5c92478754f03f5ea53bb347e81b43b294a4d1ca564ca608df053e17 CHANGELOG.md
|
6cf887df4445e9655f54950586880eacaa5767d7076387b9fb20e975bdeac7c7 CHANGELOG.md
|
||||||
2803cc34dda0304778ba0de378ec9653c1da9ba4b14200395de52022de55839e Cargo.lock
|
2803cc34dda0304778ba0de378ec9653c1da9ba4b14200395de52022de55839e Cargo.lock
|
||||||
aacc4711428f707ddc18bdbbda6257d8d7b5a1f77fce5ef2a2cc0d3042fc40d5 Cargo.toml
|
aacc4711428f707ddc18bdbbda6257d8d7b5a1f77fce5ef2a2cc0d3042fc40d5 Cargo.toml
|
||||||
239713948df0d54504989f1ab30f5bf0128b90b4e5ac45d50a132aa033323baf Dockerfile
|
239713948df0d54504989f1ab30f5bf0128b90b4e5ac45d50a132aa033323baf Dockerfile
|
||||||
f2225bc6a95a0957b89deaaf457c6fc829cacfefd45c68fc032b0f20d44d625e README.md
|
825e748c6c4e81820038819bbf66c117180fe8016a75bd33fb922d9621c50929 README.md
|
||||||
ed04220708678e9c414765900f4b4bcb1cd16d89cfb99294d92e7752a5707c7d ROADMAP.md
|
8942bd9bbeb8647b7d4c2783e116be4944537932f0eb039ee423634e30234c9c ROADMAP.md
|
||||||
da8311e3db945290666324a2f24bf4521b365272d7ac3f862ded1be993eea646 UPDATE_CHECK.toml
|
da8311e3db945290666324a2f24bf4521b365272d7ac3f862ded1be993eea646 UPDATE_CHECK.toml
|
||||||
928ba6a504bc431ae100c6e587861e5088b28822d2cb19da5d437b39d26c864a build.rs
|
928ba6a504bc431ae100c6e587861e5088b28822d2cb19da5d437b39d26c864a build.rs
|
||||||
385ac7970fa94f043d0bcf04a91184e6e2c807587b85e55517ed064bb4bddba6 deploy/README.md
|
385ac7970fa94f043d0bcf04a91184e6e2c807587b85e55517ed064bb4bddba6 deploy/README.md
|
||||||
@@ -35,7 +35,7 @@ d699f2261a0d7854e49e9b8bae44fa37008a7d2f6340a73cdc37e840722ea211 docs/API.md
|
|||||||
c6003dcbc0b95e2cfa9523b7017186cc8b4826248b588af77111ac5eb15174f9 docs/CHANGELOG_TECHNICAL_ARCHIVE.md
|
c6003dcbc0b95e2cfa9523b7017186cc8b4826248b588af77111ac5eb15174f9 docs/CHANGELOG_TECHNICAL_ARCHIVE.md
|
||||||
f2e03c3fc70607101bd69cf85f7d6ca31075b2c0f3e36a8119ff9218951517bb docs/CONTAINER.md
|
f2e03c3fc70607101bd69cf85f7d6ca31075b2c0f3e36a8119ff9218951517bb docs/CONTAINER.md
|
||||||
9538a52d508d8d7053c1387c42eef60e6d5dc1879c300b6fe951b3374c16884c docs/CUSTOM_LOCATIONS.md
|
9538a52d508d8d7053c1387c42eef60e6d5dc1879c300b6fe951b3374c16884c docs/CUSTOM_LOCATIONS.md
|
||||||
c9c4700db7b59effb6b31620c57180761f31e3f838bc2604380fa7d3ad6020e7 docs/DOCKER_DISCOVERY.md
|
16d8f59908c66e595d6003495cbf5c068c68b10aa9495eb8612c38b2de0e4a7c docs/DOCKER_DISCOVERY.md
|
||||||
9ea8db4d034ecb573976dd323da29f044538525c230df9f43a47be1ac867b24c docs/ERROR_LOGGING.md
|
9ea8db4d034ecb573976dd323da29f044538525c230df9f43a47be1ac867b24c docs/ERROR_LOGGING.md
|
||||||
bd429bc96634de84178b6b59b225fe22fe5c402acdd85d84a15685fea2dce3db docs/FILE_LOGS.md
|
bd429bc96634de84178b6b59b225fe22fe5c402acdd85d84a15685fea2dce3db docs/FILE_LOGS.md
|
||||||
df6ecd4a50796640243676ad4b3a87789f6e5d20cbebea6255e92fbfff1c7131 docs/HTTP3.md
|
df6ecd4a50796640243676ad4b3a87789f6e5d20cbebea6255e92fbfff1c7131 docs/HTTP3.md
|
||||||
@@ -58,9 +58,9 @@ ce5afb4f531bb5fb4c453deb49f643f2a563f32f7908c995e5bc8e0d7de995b7 docs/RENEWAL.m
|
|||||||
4bf7b3ea0bfe6c6b0ae0b7884b48b10ba29ff3a71611ec96957a3327d3c6ec88 docs/SECRET_STORE_BACKUP.md
|
4bf7b3ea0bfe6c6b0ae0b7884b48b10ba29ff3a71611ec96957a3327d3c6ec88 docs/SECRET_STORE_BACKUP.md
|
||||||
5dbdf45fddba198a28f511dbbd2f12bf7d2b88c41c3cbedbc20dfea3858779d3 docs/SECURITY.md
|
5dbdf45fddba198a28f511dbbd2f12bf7d2b88c41c3cbedbc20dfea3858779d3 docs/SECURITY.md
|
||||||
620b69e566d27af04f0604f4ca3f88cf95cdfea7fbc6ae9dd92446d2b2b5d9be docs/SECURITY_AUDIT.md
|
620b69e566d27af04f0604f4ca3f88cf95cdfea7fbc6ae9dd92446d2b2b5d9be docs/SECURITY_AUDIT.md
|
||||||
0a62406838257f329f5d27f74ae1867efc7d411f26e7ccaa4909420aa9b5aac9 docs/SETTINGS.md
|
632976125cbd9e96e91d1771331c73d1ac5adaa796476a20f8546971787c2529 docs/SETTINGS.md
|
||||||
3611defd206cde107e75cac006159856d12cd8f15df7ae2eb9ec3592ed2b4abd docs/STREAMS.md
|
3611defd206cde107e75cac006159856d12cd8f15df7ae2eb9ec3592ed2b4abd docs/STREAMS.md
|
||||||
da7e46207a92fa88e5db01c1516ae496fa65f4be140831e9bf7acdea3e769035 docs/TEST_REPORT.md
|
db4c14a0c8f8734339f8d7c1ecc8dcb451e2c0e590172e40ec65fe8bc537df84 docs/TEST_REPORT.md
|
||||||
cfb452d8496839e832b5fbacdd4e52525b0ecc3112fbb62340c1e580bd5c1717 docs/TODO.md
|
cfb452d8496839e832b5fbacdd4e52525b0ecc3112fbb62340c1e580bd5c1717 docs/TODO.md
|
||||||
8ee6187a5460ca45643b7fd789e27bffd264449e3a92ff70e9359edee011bbbb docs/TRANSFORM.md
|
8ee6187a5460ca45643b7fd789e27bffd264449e3a92ff70e9359edee011bbbb docs/TRANSFORM.md
|
||||||
a1e9c6d38d21067d1ce7115ca3395ae8ff1f6a4c40fb0ebf00a6940ef79df439 docs/TRANSPORT.md
|
a1e9c6d38d21067d1ce7115ca3395ae8ff1f6a4c40fb0ebf00a6940ef79df439 docs/TRANSPORT.md
|
||||||
@@ -95,7 +95,7 @@ da5ec87b9482f2fc506c4334d9365f3bfaec89254a14e5585dd6460326b20e10 docs/V0.26.4_I
|
|||||||
0ddf5215c40c8366844350bc6462d8013dba747b6f3e8fbf477985af215e5e8d docs/V0.26.5_IMPLEMENTATION.md
|
0ddf5215c40c8366844350bc6462d8013dba747b6f3e8fbf477985af215e5e8d docs/V0.26.5_IMPLEMENTATION.md
|
||||||
dd9b5dcdbd53a04fd32458caaf03b56aa335f0153b1a0e332fdf230fec12680e docs/V0.26.6_IMPLEMENTATION.md
|
dd9b5dcdbd53a04fd32458caaf03b56aa335f0153b1a0e332fdf230fec12680e docs/V0.26.6_IMPLEMENTATION.md
|
||||||
f9667fe81b31762e64d36126a7e94b609316dfa856de8f8e3b96661dd2a918c6 docs/V0.26.7_IMPLEMENTATION.md
|
f9667fe81b31762e64d36126a7e94b609316dfa856de8f8e3b96661dd2a918c6 docs/V0.26.7_IMPLEMENTATION.md
|
||||||
38cc8cd9119f211141c568c0008ae9c3d6b2c677134a4ad8ce611cd9070933da docs/V0.27.0_IMPLEMENTATION.md
|
efd5935852d4cfd09758bf67c70e437490cfce2baade46c8733201e506dbcc42 docs/V0.27.0_IMPLEMENTATION.md
|
||||||
bc2ac0117528ed4616c68cf7fe05cb1d9bbd36ecaa8573828cb3b3136923f265 docs/VHOSTS.md
|
bc2ac0117528ed4616c68cf7fe05cb1d9bbd36ecaa8573828cb3b3136923f265 docs/VHOSTS.md
|
||||||
09b60fb7b40db4d0139fa2a9e69a2aa9f28d4e61b8643521cfc7e936d7df8774 docs/VHOST_ACCESS.md
|
09b60fb7b40db4d0139fa2a9e69a2aa9f28d4e61b8643521cfc7e936d7df8774 docs/VHOST_ACCESS.md
|
||||||
4026a4adeee70f98a96cc7aa8d8be16cda42ffb2e5890d38f1ba638134ab0675 docs/WEB_SERVER.md
|
4026a4adeee70f98a96cc7aa8d8be16cda42ffb2e5890d38f1ba638134ab0675 docs/WEB_SERVER.md
|
||||||
@@ -115,8 +115,8 @@ f30e15ebe2102337933dad6f8cd334261716787073499168b389df504700a2b1 grafana/README
|
|||||||
30763fc61c38992a44bc24ad6932b88fd3b322724fce799db1f17f9a747eb59a install-debian13.sh
|
30763fc61c38992a44bc24ad6932b88fd3b322724fce799db1f17f9a747eb59a install-debian13.sh
|
||||||
858b39fa6886b71d20690bf369e76580922364b3cc7f0cf6ba9b040df9cd76e3 install.sh
|
858b39fa6886b71d20690bf369e76580922364b3cc7f0cf6ba9b040df9cd76e3 install.sh
|
||||||
29cada0936762f26495064d1524a668262ed729b21f20aebddc8b6e5cfea363b langs/README.md
|
29cada0936762f26495064d1524a668262ed729b21f20aebddc8b6e5cfea363b langs/README.md
|
||||||
49fc9fed9683b3afc56d63cd0b49d0a2d5b4dc9af1412624c9318b7b8eef513a langs/en_US.json
|
40566677252af80fe4a91c3ff8e359ba41231302c182350020d6c75298c6b847 langs/en_US.json
|
||||||
ec1d161006bc27426b9aeb7903a8ac0cffa3c8868b2a6db34197497d6efea962 langs/pl_pl.json
|
e09969817592093ea69b0cd8ec5fe661f0e686143b69b97f7b29d5f5c79920fe langs/pl_pl.json
|
||||||
2cd6a1edc556ef1712b07fc88e7ea9fdb8869ca2d73175bcd367906791cbafb1 make_zip.py
|
2cd6a1edc556ef1712b07fc88e7ea9fdb8869ca2d73175bcd367906791cbafb1 make_zip.py
|
||||||
e830d37dd1f81a4b0aa7d535f5bba69e34e433b0fd99cc8ee0b296786c32379a migrations/0002_admin.sql
|
e830d37dd1f81a4b0aa7d535f5bba69e34e433b0fd99cc8ee0b296786c32379a migrations/0002_admin.sql
|
||||||
20112cc82192098b8d602f1c4f7ca08712e9e1366c845fabb92753187c370d35 migrations/0003_certificate_renewals.sql
|
20112cc82192098b8d602f1c4f7ca08712e9e1366c845fabb92753187c370d35 migrations/0003_certificate_renewals.sql
|
||||||
@@ -136,7 +136,7 @@ edb6ee1445b01cd6f3a74a3a607f39fb107d411b49df028d2e0f4679e093de31 scripts/acme_p
|
|||||||
e69813fb1d3a4cdcfb7243964cc323fc21a603087bf2e84188fa42b9d3cee4b5 scripts/acme_rfc2136.py
|
e69813fb1d3a4cdcfb7243964cc323fc21a603087bf2e84188fa42b9d3cee4b5 scripts/acme_rfc2136.py
|
||||||
a5b4451e45ce975685772aa8409b64a57a20a7548466584c3ea7fb975e64729c scripts/admin_audit.py
|
a5b4451e45ce975685772aa8409b64a57a20a7548466584c3ea7fb975e64729c scripts/admin_audit.py
|
||||||
20e83f8b6347b819d1d1ea3de5c691c36f0816954a4210b0d3f39557fefe1931 scripts/backup.py
|
20e83f8b6347b819d1d1ea3de5c691c36f0816954a4210b0d3f39557fefe1931 scripts/backup.py
|
||||||
5076407d19a3bee94f5b99cfd846fbfa3e3b2d4bda04749451bd4c9033ab8535 scripts/check_source.py
|
c68afcc307b28e1ae12d4c841d9fe5759ecfe1e338ba7d42012cdc8366fe20cc scripts/check_source.py
|
||||||
187ee92c8029cdd59e89b4447cf4d170e856017a2091ceb85ae7c22dd1a79c72 scripts/deploy.py
|
187ee92c8029cdd59e89b4447cf4d170e856017a2091ceb85ae7c22dd1a79c72 scripts/deploy.py
|
||||||
5bb760451359cd1673d286fdffea9f0e9151af41e573371720ce4e47d86d8f48 scripts/deploy_core.py
|
5bb760451359cd1673d286fdffea9f0e9151af41e573371720ce4e47d86d8f48 scripts/deploy_core.py
|
||||||
f014472588e889488976970dbaa95a8745b6907516aa81a7cca21d0f81eaaad3 scripts/deploy_runtime.py
|
f014472588e889488976970dbaa95a8745b6907516aa81a7cca21d0f81eaaad3 scripts/deploy_runtime.py
|
||||||
@@ -151,7 +151,7 @@ d1418f8e574a7390fd45a2aa879bdf5720b773162d65e295ab0350506aa5220a scripts/mock_a
|
|||||||
2d4c859aae5ba357a6d30024c8487ae8f59f01b192711f13f9c2f8fee0f48b50 scripts/os-acme-client/README.md
|
2d4c859aae5ba357a6d30024c8487ae8f59f01b192711f13f9c2f8fee0f48b50 scripts/os-acme-client/README.md
|
||||||
c73b814a42bb4ff703441dbd177ee625055eeb115f9b5bb0c2150aede573a159 scripts/os-acme-client/opnsense-rustproxy-cert-deploy.sh
|
c73b814a42bb4ff703441dbd177ee625055eeb115f9b5bb0c2150aede573a159 scripts/os-acme-client/opnsense-rustproxy-cert-deploy.sh
|
||||||
42c5c863d01d157a8cf159218ded01ffcaac2c1f6d23be396a5708007fb39790 scripts/preflight.py
|
42c5c863d01d157a8cf159218ded01ffcaac2c1f6d23be396a5708007fb39790 scripts/preflight.py
|
||||||
ab9ed9416691581dc6c60baf9b122f2e021fa2582c097509f50b85e260934453 scripts/release_smoke.py
|
99f14c33ac4ce569eda718cee6145825847585f2ed6e18ffb12337c30e25a635 scripts/release_smoke.py
|
||||||
45be151cd85fc2ef2f1fdc3003ace63381af262e73af8a685ab48cb697cc0de1 scripts/routeros-oci-build/.env.routeros.example
|
45be151cd85fc2ef2f1fdc3003ace63381af262e73af8a685ab48cb697cc0de1 scripts/routeros-oci-build/.env.routeros.example
|
||||||
3b48cff8506e5a6ae7d3876f47721f5de7d63e2e02264a78cf5b6ddd52d9fbc6 scripts/routeros-oci-build/Dockerfile.routeros
|
3b48cff8506e5a6ae7d3876f47721f5de7d63e2e02264a78cf5b6ddd52d9fbc6 scripts/routeros-oci-build/Dockerfile.routeros
|
||||||
7c7a3e51f43b43e1c962a4b0bb591f99c1f06977bf77f23719f7f867dfe7eb8e scripts/routeros-oci-build/Dockerfile.routeros.dockerignore
|
7c7a3e51f43b43e1c962a4b0bb591f99c1f06977bf77f23719f7f867dfe7eb8e scripts/routeros-oci-build/Dockerfile.routeros.dockerignore
|
||||||
@@ -186,7 +186,7 @@ b9e57db4bd80ef37564dfc533a96897d8a494671d53acea9fb4bf28d23ba370d src/acme/provi
|
|||||||
d3210e037481e1f95e840550428e088ffd83ec9a42f1810e4c976298fb555a9a src/admin/file_logs.rs
|
d3210e037481e1f95e840550428e088ffd83ec9a42f1810e4c976298fb555a9a src/admin/file_logs.rs
|
||||||
beb8be241e4f1a8cea7b6c4e02b42f0359fb1fff10ab5ce2c70ccd0e63a554b0 src/admin/logging_api.rs
|
beb8be241e4f1a8cea7b6c4e02b42f0359fb1fff10ab5ce2c70ccd0e63a554b0 src/admin/logging_api.rs
|
||||||
58802528128f53e493f7339063433a747b605007a8842b5efc670132d897d6f7 src/admin/mod.rs
|
58802528128f53e493f7339063433a747b605007a8842b5efc670132d897d6f7 src/admin/mod.rs
|
||||||
e03abf110393aedf1fb30d540a4b772a96f39bd09d3dab6cedde39d6f08e0016 src/admin/openapi.json
|
9f62c508b8f527b19bb2b9d7592b1d82b17e8d98f5b9eaadbf24bf56f3f12418 src/admin/openapi.json
|
||||||
a53309daf118381031122ca70764f7a2f92adc44af3fc91df5f946e6856f76ae src/admin/operations.rs
|
a53309daf118381031122ca70764f7a2f92adc44af3fc91df5f946e6856f76ae src/admin/operations.rs
|
||||||
e9ea015aabdfdbb2f8dd72ea734002b5d648dc1bbef4cc4a0b85d2bcc059e9a5 src/admin/preferences.rs
|
e9ea015aabdfdbb2f8dd72ea734002b5d648dc1bbef4cc4a0b85d2bcc059e9a5 src/admin/preferences.rs
|
||||||
b4fa393b780b2676b5d72e0f90cd7290292f424b8062d4b5983e722d6ca72c32 src/admin/public.rs
|
b4fa393b780b2676b5d72e0f90cd7290292f424b8062d4b5983e722d6ca72c32 src/admin/public.rs
|
||||||
@@ -210,7 +210,7 @@ f869e4da5de149fc04ce1aab658befeaf3208c862f149ca976235d15832c3cdb src/admin/test
|
|||||||
adb56a17d6e1d517693d26c02353ed10ae277d9ce39ce15d9809ca91c9a736b1 src/admin/web/app/settings.js
|
adb56a17d6e1d517693d26c02353ed10ae277d9ce39ce15d9809ca91c9a736b1 src/admin/web/app/settings.js
|
||||||
74777adaba5a448f3a9abf3a46d91efc6eb81ff6f3b5441e5b99a9e1d6c09af0 src/admin/web/cache-panel.js
|
74777adaba5a448f3a9abf3a46d91efc6eb81ff6f3b5441e5b99a9e1d6c09af0 src/admin/web/cache-panel.js
|
||||||
50d1ebcbaf4d0b2968da23bb943fc3f67131c5d32df3f61d23ff37aad9da5b81 src/admin/web/demo.html
|
50d1ebcbaf4d0b2968da23bb943fc3f67131c5d32df3f61d23ff37aad9da5b81 src/admin/web/demo.html
|
||||||
e0be753633deff452230d444163bd01fab688bbc07f349138ada8a967bb0639b src/admin/web/docker.js
|
29861dc0739d3f27339ac2bc713355cb630998ea715cb98f150eefe19a888f58 src/admin/web/docker.js
|
||||||
d4aef376cb44b2a13174dca1cb9383f64c04b0b93279f4f0b4805e76002548a1 src/admin/web/docs.css
|
d4aef376cb44b2a13174dca1cb9383f64c04b0b93279f4f0b4805e76002548a1 src/admin/web/docs.css
|
||||||
60a4944a0a24b889296991b8af44b467f776fc85ec3597eb2e2940ef1f6fc713 src/admin/web/docs.html
|
60a4944a0a24b889296991b8af44b467f776fc85ec3597eb2e2940ef1f6fc713 src/admin/web/docs.html
|
||||||
6adb291fcc98d516fd9745d9673db16e408854a32cbf41335ae956bda11d46de src/admin/web/docs.js
|
6adb291fcc98d516fd9745d9673db16e408854a32cbf41335ae956bda11d46de src/admin/web/docs.js
|
||||||
@@ -322,9 +322,9 @@ eb0f3d5ca222d36a915493e9bb96ef34dfe3abc627ec887782f9dda6f3174754 src/db/tests.r
|
|||||||
e69031875ffec32c9f548c43bed5f1a5c4c626e9568c9173e3b093f9a8b73036 src/diagnostics.rs
|
e69031875ffec32c9f548c43bed5f1a5c4c626e9568c9173e3b093f9a8b73036 src/diagnostics.rs
|
||||||
b45d6040810c93ae2acb04ef6b0a59c189751edf9008cd81a4521c9e04e7f07d src/docker.rs
|
b45d6040810c93ae2acb04ef6b0a59c189751edf9008cd81a4521c9e04e7f07d src/docker.rs
|
||||||
93a8a3f6ba12761ddcbd19f22f32fb2c0e6948b660fb774ddd7ebdba9b6562a5 src/docker/client.rs
|
93a8a3f6ba12761ddcbd19f22f32fb2c0e6948b660fb774ddd7ebdba9b6562a5 src/docker/client.rs
|
||||||
94c59c997a3c8674aae7bfb417c2a49f6cc8bce35110a5a236738b4bf6b91f39 src/docker/model.rs
|
4c2c988191a97f81568a8df64af772463d010844f1abf327871901cdb32d4336 src/docker/model.rs
|
||||||
1ca6aecec9b5942f24451430c20fd0d7ad062d06acadde3f8c4c3743f15cae3a src/docker/reconcile.rs
|
5f4610c59b2d4ff6a205a2d9ae11bc84be689b2a68302459f546b3f43e53593c src/docker/reconcile.rs
|
||||||
4f917f124f4c2ad035f68b07ee1d7a9b62b1a5b67cbdaeba681ba365e6d5af7a src/docker/tests.rs
|
a12c47df4b90b6fc36c978a42477e6ddffbbbf69aed7252101c2fd829709bd6e src/docker/tests.rs
|
||||||
2a02ea2e010cde1b1fe99b2e6baa80ea344ea6b332dbb3c4be795b71541f64a7 src/forwarding.rs
|
2a02ea2e010cde1b1fe99b2e6baa80ea344ea6b332dbb3c4be795b71541f64a7 src/forwarding.rs
|
||||||
057e652f216a1478638cbb53b1c64ac88c7f413a65825caacbf893c5af004a63 src/forwarding/tests.rs
|
057e652f216a1478638cbb53b1c64ac88c7f413a65825caacbf893c5af004a63 src/forwarding/tests.rs
|
||||||
72215ef6911893f55cc82278169268f03d869b94728f118bf007fc555d609fde src/geoip.rs
|
72215ef6911893f55cc82278169268f03d869b94728f118bf007fc555d609fde src/geoip.rs
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ For each discovered service you can change the mapping directly in **Docker vhos
|
|||||||
- **Redirect HTTP to HTTPS**: per-app Force SSL switch. New assignments default on when the agent has a usable plain-HTTP + TLS listener pair; assignments saved before 0.18.8 retain their previous redirect-off behavior until explicitly saved with the new switch;
|
- **Redirect HTTP to HTTPS**: per-app Force SSL switch. New assignments default on when the agent has a usable plain-HTTP + TLS listener pair; assignments saved before 0.18.8 retain their previous redirect-off behavior until explicitly saved with the new switch;
|
||||||
- **WebSockets**: enable or disable classic HTTP/1.1 Upgrade forwarding for this application;
|
- **WebSockets**: enable or disable classic HTTP/1.1 Upgrade forwarding for this application;
|
||||||
- **Cache**: enable or disable normal RustProxy caching for this generated vhost;
|
- **Cache**: enable or disable normal RustProxy caching for this generated vhost;
|
||||||
- **Compression**: inherit/enable/disable dynamic compression for this published vhost and optionally filter zstd, Brotli, gzip and deflate; selecting Disabled hides/disables the codec selectors without clearing their saved values, and globally disabled codecs stay unavailable;
|
- **Compression**: one on/off checkbox for this published vhost. When enabled, Docker vhosts use the codecs and priority configured globally under **Settings -> Response**; there are no per-Docker-vhost codec selectors;
|
||||||
- **Transform**: opt this generated vhost into the global static-response transform engine; it is off by default and still requires global transformation to be enabled;
|
- **Transform**: opt this generated vhost into the global static-response transform engine; it is off by default and still requires global transformation to be enabled;
|
||||||
- **Backend health check**: HTTP/TCP/off active-probe mode, path/Host override, interval, timeout, slow threshold, rise/fall counters and accepted HTTP status range.
|
- **Backend health check**: HTTP/TCP/off active-probe mode, path/Host override, interval, timeout, slow threshold, rise/fall counters and accepted HTTP status range.
|
||||||
- **Passive Backend Health**: independent opt-in policy, OFF by default, with separate connect/timeout/I/O/HTTP-5xx/slow-response switches and optional passive rise/fall overrides.
|
- **Passive Backend Health**: independent opt-in policy, OFF by default, with separate connect/timeout/I/O/HTTP-5xx/slow-response switches and optional passive rise/fall overrides.
|
||||||
|
|||||||
+5
-6
@@ -242,12 +242,11 @@ response can disable compression at the vhost or Web Service scope when their th
|
|||||||
requires BREACH-style mitigation.
|
requires BREACH-style mitigation.
|
||||||
|
|
||||||
The global Response panel selects available codecs and the minimum size. Each ordinary
|
The global Response panel selects available codecs and the minimum size. Each ordinary
|
||||||
vhost may inherit, enable or disable dynamic compression and independently inherit/enable/disable
|
vhost and Web Server service may inherit, enable or disable dynamic compression and independently
|
||||||
zstd, Brotli, gzip and deflate. Generated Docker vhosts and Web Server services expose the same
|
inherit/enable/disable zstd, Brotli, gzip and deflate. Docker vhosts intentionally expose only one
|
||||||
per-scope codec filters. When a scope is explicitly Disabled, the dashboard hides and disables
|
Compression checkbox: when enabled they use the globally enabled codec set and priority, with no
|
||||||
those codec controls without clearing their saved values. Global codec switches remain the hard
|
per-Docker-vhost codec selectors. Global codec switches remain the hard ceiling: a local `true`
|
||||||
ceiling: a local `true` override cannot enable a codec disabled in the global Response panel.
|
override cannot enable a codec disabled in the global Response panel. `min_bytes` remains global.
|
||||||
`min_bytes` remains global.
|
|
||||||
|
|
||||||
`Vary: Accept-Encoding` is added when compression is negotiated; content length is removed
|
`Vary: Accept-Encoding` is added when compression is negotiated; content length is removed
|
||||||
for the transformed body. Strong ETags are weakened, and identity-body content digests and
|
for the transformed body. Strong ETags are weakened, and identity-body content digests and
|
||||||
|
|||||||
+2
-2
@@ -6,7 +6,7 @@ RustProxy 0.27.0 changes downstream compression policy, Docker-vhost publication
|
|||||||
|
|
||||||
Dynamic response compression defaults to zstd, Brotli and gzip enabled, with deflate opt-in. Client `Accept-Encoding` quality values are authoritative; equal quality uses deterministic `zstd -> br -> gzip -> deflate` server preference. Existing `Content-Encoding`, `no-transform`, range responses/requests, SSE and upgrades remain excluded. Cookie, authorization, `Set-Cookie`, `private` and `no-store` no longer disable compression as blanket rules.
|
Dynamic response compression defaults to zstd, Brotli and gzip enabled, with deflate opt-in. Client `Accept-Encoding` quality values are authoritative; equal quality uses deterministic `zstd -> br -> gzip -> deflate` server preference. Existing `Content-Encoding`, `no-transform`, range responses/requests, SSE and upgrades remain excluded. Cookie, authorization, `Set-Cookie`, `private` and `no-store` no longer disable compression as blanket rules.
|
||||||
|
|
||||||
Ordinary vhosts, generated Docker vhosts and Web Server services can inherit, enable or disable dynamic compression and can independently inherit/enable/disable zstd, Brotli, gzip and deflate. Global **Settings -> Response** codec switches remain the hard availability ceiling and `min_bytes` remains global. A scoped codec cannot activate a codec disabled globally. When scoped compression is explicitly Disabled, the dashboard hides and disables its codec selectors while preserving the stored override values.
|
Ordinary vhosts and Web Server services can inherit, enable or disable dynamic compression and independently inherit/enable/disable zstd, Brotli, gzip and deflate. Docker vhosts expose one Compression checkbox only and use the codec set/priorities from global **Settings -> Response**. Global codec switches remain the hard availability ceiling and `min_bytes` remains global.
|
||||||
|
|
||||||
An explicitly published Docker assignment keeps its generated hostname even when its service disappears. A successful inventory without the assigned service materializes an unavailable route that returns HTTP 503 instead of removing the hostname. Agent polling errors retain the previous successful inventory when one exists, and a returning service is reconciled automatically. The cache overview progress elements have explicit WebKit/Chromium and Firefox progress-value styling so their visual fill follows the numeric meter value.
|
An explicitly published Docker assignment keeps its generated hostname even when its service disappears. A successful inventory without the assigned service materializes an unavailable route that returns HTTP 503 instead of removing the hostname. Agent polling errors retain the previous successful inventory when one exists, and a returning service is reconciled automatically. The cache overview progress elements have explicit WebKit/Chromium and Firefox progress-value styling so their visual fill follows the numeric meter value.
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ Fresh installations now default the response `Server` policy to `custom` with th
|
|||||||
|
|
||||||
## Regression coverage
|
## Regression coverage
|
||||||
|
|
||||||
Compression unit coverage checks defaults, q-value negotiation, equal-quality priority, each supported codec, existing-encoding passthrough, scoped per-codec resolution and the revised cookie/auth/cache-privacy policy. Docker unit coverage checks missing published service -> retained 503, failed agent observation -> retained last-known backend and persistence of Docker codec overrides. Settings coverage checks the fresh-install `Server: RustProxy` default and legacy missing-field compatibility. Static/UI contracts require ordinary-vhost, Docker-vhost and Web-Service codec controls to hide/disable when their scope is explicitly OFF without clearing saved values, plus the 503 path, visible cache progress styling, external Debian-packaging separation and reproducible archives without a `debian/` tree.
|
Compression unit coverage checks defaults, q-value negotiation, equal-quality priority, each supported codec, existing-encoding passthrough, scoped per-codec resolution and the revised cookie/auth/cache-privacy policy. Docker unit coverage checks missing published service -> retained 503, failed agent observation -> retained last-known backend, the single compression switch and ignoring legacy Docker per-codec values. Settings coverage checks the fresh-install `Server: RustProxy` default and legacy missing-field compatibility. Static/UI contracts require ordinary-vhost and Web-Service codec controls to hide/disable when their scope is explicitly OFF, require Docker vhosts to expose only the single Compression checkbox, and retain the 503 path, visible cache progress styling, external Debian-packaging separation and reproducible archives without a `debian/` tree.
|
||||||
|
|
||||||
## Verification status in this workspace
|
## Verification status in this workspace
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Scope
|
## Scope
|
||||||
|
|
||||||
0.27.0 changes downstream compression defaults/negotiation, makes Docker publications persistent across transient service loss, adds scoped compression overrides, and fixes cache occupancy meter rendering. SQLite remains schema 8. Saved configuration changes are additive/defaulted: vhosts and Web Services gain scoped compression/codec overrides and Docker assignments gain nullable compression/codec fields. Fresh installations also default the `Server` header policy to `custom: RustProxy`, while a missing legacy field still deserializes with the previous preserve behavior.
|
0.27.0 changes downstream compression defaults/negotiation, makes Docker publications persistent across transient service loss, adds scoped compression overrides, and fixes cache occupancy meter rendering. SQLite remains schema 8. Saved configuration changes are additive/defaulted: vhosts and Web Services gain scoped compression/codec overrides, while Docker assignments use one nullable compression switch. Legacy pre-release Docker codec fields remain accepted for configuration compatibility but are ignored. Fresh installations also default the `Server` header policy to `custom: RustProxy`, while a missing legacy field still deserializes with the previous preserve behavior.
|
||||||
|
|
||||||
## Compression
|
## Compression
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ Global compression defaults to zstd, Brotli and gzip enabled, with deflate disab
|
|||||||
|
|
||||||
Responses carrying `Cookie`, `Authorization`, `Set-Cookie`, `Cache-Control: private` or `no-store` are no longer rejected merely because of those headers. Compression remains disabled for existing `Content-Encoding`, `no-transform`, request ranges/`Content-Range`, SSE, upgrades, HEAD and non-body statuses. Existing encoded bodies are never recompressed.
|
Responses carrying `Cookie`, `Authorization`, `Set-Cookie`, `Cache-Control: private` or `no-store` are no longer rejected merely because of those headers. Compression remains disabled for existing `Content-Encoding`, `no-transform`, request ranges/`Content-Range`, SSE, upgrades, HEAD and non-body statuses. Existing encoded bodies are never recompressed.
|
||||||
|
|
||||||
Ordinary vhosts, generated Docker vhosts and Web Server services expose inherit/enable/disable dynamic-compression policy plus individual zstd/Brotli/gzip/deflate overrides. Global Response codec switches remain the hard availability ceiling and the minimum size remains global. A child scope may re-enable a codec disabled by an enclosing scope only when that codec is still enabled globally. In the dashboard, explicitly selecting **Disabled** hides and disables the child codec selectors; their stored values are preserved so changing the scope back to Inherit/Enabled restores the previous choices.
|
Ordinary vhosts and Web Server services expose inherit/enable/disable dynamic-compression policy plus individual zstd/Brotli/gzip/deflate overrides. Global Response codec switches remain the hard availability ceiling and the minimum size remains global. Docker vhosts intentionally expose one Compression checkbox only; when enabled, the generated vhost uses the globally enabled codec set and deterministic global priority. Legacy Docker per-codec values are ignored and the dashboard clears them to null when an assignment is saved.
|
||||||
|
|
||||||
## Persistent Docker publications
|
## Persistent Docker publications
|
||||||
|
|
||||||
@@ -24,4 +24,4 @@ The `/cache` JavaScript already calculates occupancy percentages from configured
|
|||||||
|
|
||||||
## Compatibility and verification
|
## Compatibility and verification
|
||||||
|
|
||||||
No SQLite migration is required. Older vhost, Docker assignment and Web Service documents load with inherited compression behavior because all new fields are defaulted. Existing stored `server_header` settings are preserved; documents predating that field keep the historical preserve behavior. Rust compiler/runtime verification remains mandatory on the release host; Rust-independent checks in `docs/TEST_REPORT.md` do not substitute for `cargo fmt`, `cargo check`, Clippy, tests or live protocol acceptance.
|
No SQLite migration is required. Older vhost, Docker assignment and Web Service documents load because all new fields are defaulted; legacy Docker codec fields are tolerated but no longer affect generated vhosts. Existing stored `server_header` settings are preserved; documents predating that field keep the historical preserve behavior. Rust compiler/runtime verification remains mandatory on the release host; Rust-independent checks in `docs/TEST_REPORT.md` do not substitute for `cargo fmt`, `cargo check`, Clippy, tests or live protocol acceptance.
|
||||||
+1
-1
@@ -1486,7 +1486,7 @@
|
|||||||
"dockerForceSslUnavailable": "Requires an active plain HTTP listener and one unambiguous TLS listener on this agent.",
|
"dockerForceSslUnavailable": "Requires an active plain HTTP listener and one unambiguous TLS listener on this agent.",
|
||||||
"dockerWebsockets": "WebSockets",
|
"dockerWebsockets": "WebSockets",
|
||||||
"dockerCompression": "Compression",
|
"dockerCompression": "Compression",
|
||||||
"dockerCompressionHelp": "Inherit, enable or disable compression for this Docker vhost and optionally filter individual globally enabled codecs.",
|
"dockerCompressionHelp": "Enable or disable compression for this Docker vhost. The enabled codecs and their priority come from global Response settings.",
|
||||||
"dockerCache": "Cache",
|
"dockerCache": "Cache",
|
||||||
"vhProxyTimeouts": "Proxy timeouts",
|
"vhProxyTimeouts": "Proxy timeouts",
|
||||||
"vhProxyConnectTimeout": "Proxy connect timeout (s)",
|
"vhProxyConnectTimeout": "Proxy connect timeout (s)",
|
||||||
|
|||||||
+1
-1
@@ -1486,7 +1486,7 @@
|
|||||||
"dockerForceSslUnavailable": "Wymaga aktywnego listenera zwykłego HTTP oraz jednego jednoznacznego listenera TLS dla tego agenta.",
|
"dockerForceSslUnavailable": "Wymaga aktywnego listenera zwykłego HTTP oraz jednego jednoznacznego listenera TLS dla tego agenta.",
|
||||||
"dockerWebsockets": "WebSockety",
|
"dockerWebsockets": "WebSockety",
|
||||||
"dockerCompression": "Kompresja",
|
"dockerCompression": "Kompresja",
|
||||||
"dockerCompressionHelp": "Dziedzicz, włącz albo wyłącz kompresję dla tego vhosta Docker oraz opcjonalnie ogranicz poszczególne globalnie włączone kodeki.",
|
"dockerCompressionHelp": "Włącz lub wyłącz kompresję dla tego vhosta Docker. Dostępne kodeki i ich priorytet wynikają z globalnych ustawień Response.",
|
||||||
"dockerCache": "Cache",
|
"dockerCache": "Cache",
|
||||||
"vhProxyTimeouts": "Timeouty proxy",
|
"vhProxyTimeouts": "Timeouty proxy",
|
||||||
"vhProxyConnectTimeout": "Proxy connect timeout (s)",
|
"vhProxyConnectTimeout": "Proxy connect timeout (s)",
|
||||||
|
|||||||
@@ -813,10 +813,13 @@ for marker in [
|
|||||||
]:
|
]:
|
||||||
assert marker in vhosts_js, marker
|
assert marker in vhosts_js, marker
|
||||||
for marker in [
|
for marker in [
|
||||||
'const compressionFields = [[labeled("compressionZstd"',
|
'compressionEnabled.checked = assignment?.compression_enabled !== false',
|
||||||
'field.hidden = disabled; control.disabled = disabled',
|
'compression_zstd: null, compression_br: null, compression_gzip: null, compression_deflate: null',
|
||||||
|
'switches.append(preserveLabel, forceSslField, websocketField, cacheField, compressionField, transformField)',
|
||||||
]:
|
]:
|
||||||
assert marker in docker_ui, marker
|
assert marker in docker_ui, marker
|
||||||
|
for forbidden in ['.docker-compression-zstd', '.docker-compression-br', '.docker-compression-gzip', '.docker-compression-deflate', 'compressionSelect(']:
|
||||||
|
assert forbidden not in docker_ui, forbidden
|
||||||
assert 'id="web-service-compression-options"' in html
|
assert 'id="web-service-compression-options"' in html
|
||||||
for marker in [
|
for marker in [
|
||||||
'function syncCompression()',
|
'function syncCompression()',
|
||||||
@@ -864,9 +867,9 @@ assert "dockerOpenApp" in docker_ui and "proxiedUrl(agent, hostname)" in docker_
|
|||||||
# 0.19.0 Docker-vhost controls: chip aliases, default agent ACL, redirect/WebSockets/cache.
|
# 0.19.0 Docker-vhost controls: chip aliases, default agent ACL, redirect/WebSockets/cache.
|
||||||
docker_source = rust_source(root, "src/docker.rs")
|
docker_source = rust_source(root, "src/docker.rs")
|
||||||
management_ui = (root / "src/admin/web/management.js").read_text()
|
management_ui = (root / "src/admin/web/management.js").read_text()
|
||||||
for marker in ["function aliasEditor(", "host-chip-editor docker-alias-editor", ".docker-force-ssl", ".docker-websockets", ".docker-cache-enabled", ".docker-compression-enabled", ".docker-compression-zstd", ".docker-compression-br", ".docker-compression-gzip", ".docker-compression-deflate", ".docker-agent-acl-profile"]:
|
for marker in ["function aliasEditor(", "host-chip-editor docker-alias-editor", ".docker-force-ssl", ".docker-websockets", ".docker-cache-enabled", ".docker-compression-enabled", ".docker-agent-acl-profile"]:
|
||||||
assert marker in docker_ui, marker
|
assert marker in docker_ui, marker
|
||||||
for marker in ['"force_ssl": assignment.force_ssl.unwrap_or(false)', '"websockets": assignment.websockets', '"enabled": assignment.compression_enabled', '"zstd": assignment.compression_zstd', '"br": assignment.compression_br', '"gzip": assignment.compression_gzip', '"deflate": assignment.compression_deflate', '"cache": {"enabled": assignment.cache_enabled}', 'assignment.acl_profile_id.clone().or_else(|| agent.acl_profile_id.clone())', 'host.transient_unavailable = target.is_none()', 'inventory: previous_inventory']:
|
for marker in ['"force_ssl": assignment.force_ssl.unwrap_or(false)', '"websockets": assignment.websockets', '"enabled": assignment.compression_enabled', '"cache": {"enabled": assignment.cache_enabled}', 'assignment.acl_profile_id.clone().or_else(|| agent.acl_profile_id.clone())', 'host.transient_unavailable = target.is_none()', 'inventory: previous_inventory']:
|
||||||
assert marker in docker_source, marker
|
assert marker in docker_source, marker
|
||||||
for marker in ["published_assignment_stays_routable_as_503_when_service_is_missing", "failed_agent_observation_with_last_inventory_keeps_backend_materialized", "disabling_agent_stops_discovery_but_keeps_published_hostname_as_503"]:
|
for marker in ["published_assignment_stays_routable_as_503_when_service_is_missing", "failed_agent_observation_with_last_inventory_keeps_backend_materialized", "disabling_agent_stops_discovery_but_keeps_published_hostname_as_503"]:
|
||||||
assert marker in docker_source, marker
|
assert marker in docker_source, marker
|
||||||
|
|||||||
@@ -1018,9 +1018,13 @@ def source_contract_smoke() -> None:
|
|||||||
assert 'status.backend_pool_domains' in vhosts_ui and 'payload["backend_pool_domains"]' in admin
|
assert 'status.backend_pool_domains' in vhosts_ui and 'payload["backend_pool_domains"]' in admin
|
||||||
docker_source = rust_source(ROOT, 'src/docker.rs')
|
docker_source = rust_source(ROOT, 'src/docker.rs')
|
||||||
management_ui = (ROOT / 'src/admin/web/management.js').read_text(encoding='utf-8')
|
management_ui = (ROOT / 'src/admin/web/management.js').read_text(encoding='utf-8')
|
||||||
for marker in ['function aliasEditor(', 'host-chip-editor docker-alias-editor', '.docker-force-ssl', '.docker-websockets', '.docker-cache-enabled', '.docker-compression-enabled', '.docker-compression-zstd', '.docker-compression-br', '.docker-compression-gzip', '.docker-compression-deflate', '.docker-passive-enabled', '.docker-passive-5xx', '.docker-agent-acl-profile']:
|
for marker in ['function aliasEditor(', 'host-chip-editor docker-alias-editor', '.docker-force-ssl', '.docker-websockets', '.docker-cache-enabled', '.docker-compression-enabled', '.docker-passive-enabled', '.docker-passive-5xx', '.docker-agent-acl-profile']:
|
||||||
assert marker in docker_ui, marker
|
assert marker in docker_ui, marker
|
||||||
for marker in ['"force_ssl": assignment.force_ssl.unwrap_or(false)', '"websockets": assignment.websockets', '"enabled": assignment.compression_enabled', '"zstd": assignment.compression_zstd', '"br": assignment.compression_br', '"gzip": assignment.compression_gzip', '"deflate": assignment.compression_deflate', '"cache": {"enabled": assignment.cache_enabled}', '"passive_health": assignment.passive_health.clone()', 'assignment.acl_profile_id.clone().or_else(|| agent.acl_profile_id.clone())', 'host.transient_unavailable = target.is_none()', 'inventory: previous_inventory']:
|
for forbidden in ['.docker-compression-zstd', '.docker-compression-br', '.docker-compression-gzip', '.docker-compression-deflate', 'compressionSelect(']:
|
||||||
|
assert forbidden not in docker_ui, forbidden
|
||||||
|
assert 'compressionEnabled.checked = assignment?.compression_enabled !== false' in docker_ui
|
||||||
|
assert 'compression_zstd: null, compression_br: null, compression_gzip: null, compression_deflate: null' in docker_ui
|
||||||
|
for marker in ['"force_ssl": assignment.force_ssl.unwrap_or(false)', '"websockets": assignment.websockets', '"enabled": assignment.compression_enabled', '"cache": {"enabled": assignment.cache_enabled}', '"passive_health": assignment.passive_health.clone()', 'assignment.acl_profile_id.clone().or_else(|| agent.acl_profile_id.clone())', 'host.transient_unavailable = target.is_none()', 'inventory: previous_inventory']:
|
||||||
assert marker in docker_source, marker
|
assert marker in docker_source, marker
|
||||||
route_cache_0270 = rust_source(ROOT, 'src/proxy/forward/route_cache.rs')
|
route_cache_0270 = rust_source(ROOT, 'src/proxy/forward/route_cache.rs')
|
||||||
for marker in ['if route.unavailable', 'StatusCode::SERVICE_UNAVAILABLE', 'published Docker service is currently unavailable', 'retry-after']:
|
for marker in ['if route.unavailable', 'StatusCode::SERVICE_UNAVAILABLE', 'published Docker service is currently unavailable', 'retry-after']:
|
||||||
|
|||||||
+10
-6
@@ -2424,31 +2424,35 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"description": "Per-published-vhost dynamic compression override. null inherits the enclosing/global policy; true/false enables or disables the scope."
|
"description": "Single per-Docker-vhost dynamic compression switch. null inherits the global policy; true/false enables or disables compression for this publication. Codec availability and priority come from global Response settings."
|
||||||
},
|
},
|
||||||
"compression_zstd": {
|
"compression_zstd": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"description": "Optional per-Docker-vhost Zstandard override. null inherits; globally disabled codecs remain unavailable."
|
"description": "Legacy compatibility field accepted when loading older 0.27.0 pre-release configuration. Ignored for Docker vhosts; Zstandard availability is controlled by global Response settings.",
|
||||||
|
"deprecated": true
|
||||||
},
|
},
|
||||||
"compression_br": {
|
"compression_br": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"description": "Optional per-Docker-vhost Brotli override. null inherits; globally disabled codecs remain unavailable."
|
"description": "Legacy compatibility field accepted when loading older 0.27.0 pre-release configuration. Ignored for Docker vhosts; Brotli availability is controlled by global Response settings.",
|
||||||
|
"deprecated": true
|
||||||
},
|
},
|
||||||
"compression_gzip": {
|
"compression_gzip": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"description": "Optional per-Docker-vhost gzip override. null inherits; globally disabled codecs remain unavailable."
|
"description": "Legacy compatibility field accepted when loading older 0.27.0 pre-release configuration. Ignored for Docker vhosts; gzip availability is controlled by global Response settings.",
|
||||||
|
"deprecated": true
|
||||||
},
|
},
|
||||||
"compression_deflate": {
|
"compression_deflate": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
"default": null,
|
"default": null,
|
||||||
"description": "Optional per-Docker-vhost deflate override. null inherits; globally disabled codecs remain unavailable."
|
"description": "Legacy compatibility field accepted when loading older 0.27.0 pre-release configuration. Ignored for Docker vhosts; deflate availability is controlled by global Response settings.",
|
||||||
|
"deprecated": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@@ -5524,7 +5528,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"description": "Sets an HttpOnly SameSite=Strict session cookie. Browser sessions use the configured 7–30 day absolute lifetime. Use the panel sign-in page. No bearer token or URL token is accepted.",
|
"description": "Sets an HttpOnly SameSite=Strict session cookie. Browser sessions use the configured 7\u201330 day absolute lifetime. Use the panel sign-in page. No bearer token or URL token is accepted.",
|
||||||
"security": [],
|
"security": [],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
|
|||||||
+6
-10
@@ -251,8 +251,9 @@
|
|||||||
const inline = row.querySelector(".docker-acl-inline")?.checked;
|
const inline = row.querySelector(".docker-acl-inline")?.checked;
|
||||||
return {
|
return {
|
||||||
service_key: row.dataset.key, hostname: row.querySelector(".docker-hostname").value.trim().toLowerCase(), aliases: row._readAliases?.() || [], target_ip: row.querySelector(".docker-target-ip").value || null,
|
service_key: row.dataset.key, hostname: row.querySelector(".docker-hostname").value.trim().toLowerCase(), aliases: row._readAliases?.() || [], target_ip: row.querySelector(".docker-target-ip").value || null,
|
||||||
enabled: true, scheme: row.querySelector(".docker-scheme").value, preserve_host: row.querySelector(".docker-preserve-host").checked, force_ssl: row.querySelector(".docker-force-ssl").checked, websockets: row.querySelector(".docker-websockets").checked, cache_enabled: row.querySelector(".docker-cache-enabled").checked, transform_enabled: row.querySelector(".docker-transform-enabled").checked, compression_enabled: (() => { const value = row.querySelector(".docker-compression-enabled").value; return value === "" ? null : value === "on"; })(),
|
enabled: true, scheme: row.querySelector(".docker-scheme").value, preserve_host: row.querySelector(".docker-preserve-host").checked, force_ssl: row.querySelector(".docker-force-ssl").checked, websockets: row.querySelector(".docker-websockets").checked, cache_enabled: row.querySelector(".docker-cache-enabled").checked, transform_enabled: row.querySelector(".docker-transform-enabled").checked, compression_enabled: row.querySelector(".docker-compression-enabled").checked,
|
||||||
compression_zstd: (() => { const value = row.querySelector(".docker-compression-zstd").value; return value === "" ? null : value === "on"; })(), compression_br: (() => { const value = row.querySelector(".docker-compression-br").value; return value === "" ? null : value === "on"; })(), compression_gzip: (() => { const value = row.querySelector(".docker-compression-gzip").value; return value === "" ? null : value === "on"; })(), compression_deflate: (() => { const value = row.querySelector(".docker-compression-deflate").value; return value === "" ? null : value === "on"; })(),
|
// Docker publications intentionally expose one compression switch only. Codec selection stays global.
|
||||||
|
compression_zstd: null, compression_br: null, compression_gzip: null, compression_deflate: null,
|
||||||
acl_profile_id: row.querySelector(".docker-acl-profile")?.value || null, acl: inline ? { default: row.querySelector(".docker-acl-default").value, rules: parseRules(row.querySelector(".docker-acl-rules").value) } : null,
|
acl_profile_id: row.querySelector(".docker-acl-profile")?.value || null, acl: inline ? { default: row.querySelector(".docker-acl-default").value, rules: parseRules(row.querySelector(".docker-acl-rules").value) } : null,
|
||||||
proxy_timeouts: { connect_timeout_seconds: Number(row.querySelector(".docker-proxy-connect").value), response_header_timeout_seconds: Number(row.querySelector(".docker-proxy-header").value), read_timeout_seconds: Number(row.querySelector(".docker-proxy-read").value), send_timeout_seconds: Number(row.querySelector(".docker-proxy-send").value) },
|
proxy_timeouts: { connect_timeout_seconds: Number(row.querySelector(".docker-proxy-connect").value), response_header_timeout_seconds: Number(row.querySelector(".docker-proxy-header").value), read_timeout_seconds: Number(row.querySelector(".docker-proxy-read").value), send_timeout_seconds: Number(row.querySelector(".docker-proxy-send").value) },
|
||||||
health_check: collectHealth(row), passive_health: collectPassiveHealth(row)
|
health_check: collectHealth(row), passive_health: collectPassiveHealth(row)
|
||||||
@@ -289,14 +290,9 @@
|
|||||||
const websockets = input("", "checkbox", "docker-websockets"); websockets.checked = assignment?.websockets !== false; const websocketField = checkboxField("dockerWebsockets", websockets);
|
const websockets = input("", "checkbox", "docker-websockets"); websockets.checked = assignment?.websockets !== false; const websocketField = checkboxField("dockerWebsockets", websockets);
|
||||||
const cacheEnabled = input("", "checkbox", "docker-cache-enabled"); cacheEnabled.checked = assignment?.cache_enabled === true; const cacheField = checkboxField("dockerCache", cacheEnabled);
|
const cacheEnabled = input("", "checkbox", "docker-cache-enabled"); cacheEnabled.checked = assignment?.cache_enabled === true; const cacheField = checkboxField("dockerCache", cacheEnabled);
|
||||||
const transformEnabled = input("", "checkbox", "docker-transform-enabled"); transformEnabled.checked = assignment?.transform_enabled === true; const transformField = checkboxField("dockerTransform", transformEnabled);
|
const transformEnabled = input("", "checkbox", "docker-transform-enabled"); transformEnabled.checked = assignment?.transform_enabled === true; const transformField = checkboxField("dockerTransform", transformEnabled);
|
||||||
const compressionSelect = (className, current) => { const select = el("select", undefined, className); for (const [value, keyName] of [["", "inherit"], ["on", "enabled"], ["off", "notEnabled"]]) { const option = el("option", t(keyName)); option.value = value; select.append(option); } select.value = current === true ? "on" : current === false ? "off" : ""; return select; };
|
const compressionEnabled = input("", "checkbox", "docker-compression-enabled"); compressionEnabled.checked = assignment?.compression_enabled !== false; const compressionField = checkboxField("dockerCompression", compressionEnabled); compressionField.title = t("dockerCompressionHelp");
|
||||||
const compressionEnabled = compressionSelect("docker-compression-enabled", assignment?.compression_enabled);
|
const switches = el("div", undefined, "docker-switch-row"); switches.append(preserveLabel, forceSslField, websocketField, cacheField, compressionField, transformField);
|
||||||
const compressionZstd = compressionSelect("docker-compression-zstd", assignment?.compression_zstd), compressionBr = compressionSelect("docker-compression-br", assignment?.compression_br), compressionGzip = compressionSelect("docker-compression-gzip", assignment?.compression_gzip), compressionDeflate = compressionSelect("docker-compression-deflate", assignment?.compression_deflate);
|
route.append(labeled("dockerHostname", host, t("dockerHostnameHelp").replace("{domain}", agent.base_domain)), aliases.node, labeled("dockerBackendIp", target), labeled("dockerBackendScheme", scheme), switches);
|
||||||
const compressionFields = [[labeled("compressionZstd", compressionZstd), compressionZstd], [labeled("compressionBr", compressionBr), compressionBr], [labeled("compressionGzip", compressionGzip), compressionGzip], [labeled("compressionDeflate", compressionDeflate), compressionDeflate]];
|
|
||||||
const syncCompressionVisibility = () => { const disabled = compressionEnabled.value === "off"; for (const [field, control] of compressionFields) { field.hidden = disabled; control.disabled = disabled; } };
|
|
||||||
compressionEnabled.addEventListener("change", syncCompressionVisibility); syncCompressionVisibility();
|
|
||||||
const switches = el("div", undefined, "docker-switch-row"); switches.append(preserveLabel, forceSslField, websocketField, cacheField, transformField);
|
|
||||||
route.append(labeled("dockerHostname", host, t("dockerHostnameHelp").replace("{domain}", agent.base_domain)), aliases.node, labeled("dockerBackendIp", target), labeled("dockerBackendScheme", scheme), labeled("dockerCompression", compressionEnabled, t("dockerCompressionHelp")), ...compressionFields.map(([field]) => field), switches);
|
|
||||||
editor.append(route, aclEditor(assignment, agent), timeoutEditor(assignment), healthEditor(assignment), passiveHealthEditor(assignment));
|
editor.append(route, aclEditor(assignment, agent), timeoutEditor(assignment), healthEditor(assignment), passiveHealthEditor(assignment));
|
||||||
const actions = el("div", undefined, "docker-service-actions"), apply = el("button", t("dockerApplyService"), "outline docker-apply"); apply.type = "button"; apply.disabled = !publish.checked; apply.addEventListener("click", async () => { apply.disabled = true; try { await saveAssignment(agent.id, row, true); } catch (error) { toast(error.message, true); } finally { if (row.isConnected) apply.disabled = !publish.checked; } }); actions.append(apply); editor.append(actions); row.append(editor);
|
const actions = el("div", undefined, "docker-service-actions"), apply = el("button", t("dockerApplyService"), "outline docker-apply"); apply.type = "button"; apply.disabled = !publish.checked; apply.addEventListener("click", async () => { apply.disabled = true; try { await saveAssignment(agent.id, row, true); } catch (error) { toast(error.message, true); } finally { if (row.isConnected) apply.disabled = !publish.checked; } }); actions.append(apply); editor.append(actions); row.append(editor);
|
||||||
function updateHint() { const targetLabel = target.selectedOptions?.[0]?.textContent || t("dockerBackendIpAuto"), aliasCount = aliases.count(); editorHint.textContent = `${host.value.trim() || technical} → ${scheme.value.toUpperCase()} · ${targetLabel}${aliasCount ? ` · +${aliasCount} ${t("dockerAliasesShort")}` : ""}`; } updateHint();
|
function updateHint() { const targetLabel = target.selectedOptions?.[0]?.textContent || t("dockerBackendIpAuto"), aliasCount = aliases.count(); editorHint.textContent = `${host.value.trim() || technical} → ${scheme.value.toUpperCase()} · ${targetLabel}${aliasCount ? ` · +${aliasCount} ${t("dockerAliasesShort")}` : ""}`; } updateHint();
|
||||||
|
|||||||
@@ -110,7 +110,10 @@ pub struct Assignment {
|
|||||||
/// the per-app redirect switch existed. New UI assignments persist true.
|
/// the per-app redirect switch existed. New UI assignments persist true.
|
||||||
pub force_ssl: Option<bool>,
|
pub force_ssl: Option<bool>,
|
||||||
pub websockets: bool,
|
pub websockets: bool,
|
||||||
|
/// Single Docker-vhost dynamic-compression switch. None inherits the global policy.
|
||||||
pub compression_enabled: Option<bool>,
|
pub compression_enabled: Option<bool>,
|
||||||
|
/// Legacy pre-release 0.27.0 fields kept for saved-config compatibility. Docker
|
||||||
|
/// reconciliation ignores per-codec overrides; codecs are selected globally.
|
||||||
pub compression_gzip: Option<bool>,
|
pub compression_gzip: Option<bool>,
|
||||||
pub compression_br: Option<bool>,
|
pub compression_br: Option<bool>,
|
||||||
pub compression_zstd: Option<bool>,
|
pub compression_zstd: Option<bool>,
|
||||||
|
|||||||
@@ -118,13 +118,9 @@ pub fn effective_config(
|
|||||||
"force_ssl": assignment.force_ssl.unwrap_or(false),
|
"force_ssl": assignment.force_ssl.unwrap_or(false),
|
||||||
"websockets": assignment.websockets,
|
"websockets": assignment.websockets,
|
||||||
"backends": backends,
|
"backends": backends,
|
||||||
"compression": {
|
// Docker publications intentionally use one compression switch. The enabled
|
||||||
"enabled": assignment.compression_enabled,
|
// codec set is inherited from global Response settings.
|
||||||
"gzip": assignment.compression_gzip,
|
"compression": {"enabled": assignment.compression_enabled},
|
||||||
"br": assignment.compression_br,
|
|
||||||
"zstd": assignment.compression_zstd,
|
|
||||||
"deflate": assignment.compression_deflate
|
|
||||||
},
|
|
||||||
"cache": {"enabled": assignment.cache_enabled},
|
"cache": {"enabled": assignment.cache_enabled},
|
||||||
"transform": {"enabled": assignment.transform_enabled},
|
"transform": {"enabled": assignment.transform_enabled},
|
||||||
"acl_profile_id": assignment.acl_profile_id.clone().or_else(|| agent.acl_profile_id.clone()),
|
"acl_profile_id": assignment.acl_profile_id.clone().or_else(|| agent.acl_profile_id.clone()),
|
||||||
|
|||||||
+4
-3
@@ -233,7 +233,7 @@ mod tests {
|
|||||||
assert!(effective.vhosts[0].backends.is_empty());
|
assert!(effective.vhosts[0].backends.is_empty());
|
||||||
assert!(effective.vhosts[0].transient_unavailable);
|
assert!(effective.vhosts[0].transient_unavailable);
|
||||||
assert_eq!(effective.vhosts[0].compression.enabled, Some(false));
|
assert_eq!(effective.vhosts[0].compression.enabled, Some(false));
|
||||||
assert_eq!(effective.vhosts[0].compression.zstd, Some(false));
|
assert_eq!(effective.vhosts[0].compression.zstd, None);
|
||||||
|
|
||||||
let policy = crate::config::ValidationPolicy {
|
let policy = crate::config::ValidationPolicy {
|
||||||
proxy_addr: "127.0.0.1:8080".parse().unwrap(),
|
proxy_addr: "127.0.0.1:8080".parse().unwrap(),
|
||||||
@@ -271,6 +271,7 @@ mod tests {
|
|||||||
service_key: "container:app:8080/tcp".into(),
|
service_key: "container:app:8080/tcp".into(),
|
||||||
hostname: "app".into(),
|
hostname: "app".into(),
|
||||||
compression_enabled: Some(true),
|
compression_enabled: Some(true),
|
||||||
|
// Legacy per-codec values must not affect Docker vhosts.
|
||||||
compression_gzip: Some(false),
|
compression_gzip: Some(false),
|
||||||
compression_br: Some(true),
|
compression_br: Some(true),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@@ -294,8 +295,8 @@ mod tests {
|
|||||||
assert_eq!(effective.vhosts[0].backends.len(), 1);
|
assert_eq!(effective.vhosts[0].backends.len(), 1);
|
||||||
assert!(!effective.vhosts[0].transient_unavailable);
|
assert!(!effective.vhosts[0].transient_unavailable);
|
||||||
assert_eq!(effective.vhosts[0].compression.enabled, Some(true));
|
assert_eq!(effective.vhosts[0].compression.enabled, Some(true));
|
||||||
assert_eq!(effective.vhosts[0].compression.gzip, Some(false));
|
assert_eq!(effective.vhosts[0].compression.gzip, None);
|
||||||
assert_eq!(effective.vhosts[0].compression.br, Some(true));
|
assert_eq!(effective.vhosts[0].compression.br, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in new issue
Block a user