diff --git a/architecture.html b/architecture.html index 14ec734..350ebfc 100644 --- a/architecture.html +++ b/architecture.html @@ -23,7 +23,7 @@ - + - + diff --git a/cloud.html b/cloud.html index ff29212..af09550 100644 --- a/cloud.html +++ b/cloud.html @@ -23,7 +23,7 @@ - + - + diff --git a/guidelines.html b/guidelines.html index e1dde85..c35be73 100644 --- a/guidelines.html +++ b/guidelines.html @@ -23,7 +23,7 @@ - + - + diff --git a/index.html b/index.html index d931b46..75e1819 100644 --- a/index.html +++ b/index.html @@ -23,7 +23,7 @@ - + - + @@ -91,7 +91,7 @@

Composable, mesh-native applianc See the roadmap -
+
wg0 · mesh · IPv6 @@ -257,7 +257,7 @@

Advanced, cloud advanced

Three gates before the application

In an advanced installation, a request meets CrowdSec first, then Nginx with the WAF inline, then Anubis, and only then the application. Decided, 0030

-
+
  1. InternetA request arrives, over IPv6 first.
  2. @@ -292,7 +292,7 @@

    Declared in one file, converged by one command

    -
    +
    root@blog: ~ diff --git a/roadmap.html b/roadmap.html index b1d5d61..001bd35 100644 --- a/roadmap.html +++ b/roadmap.html @@ -23,7 +23,7 @@ - + - + diff --git a/security.html b/security.html index 3db85bb..f6414d3 100644 --- a/security.html +++ b/security.html @@ -23,7 +23,7 @@ - + - + @@ -112,7 +112,7 @@

    Keys and identity: none in the image

    The request pipeline

    Keel Web is an appliance of its own and the base of every web appliance: Nginx, the Coraza WAF and Anubis. In an advanced installation a request passes them in a fixed order. Decided, 0029 and 0030; Phases 1 and 3

    -
    +
    1. InternetA request arrives, over IPv6 first.
    2. diff --git a/tests/test_sitecheck.py b/tests/test_sitecheck.py index 7e1aaf4..6fe9184 100644 --- a/tests/test_sitecheck.py +++ b/tests/test_sitecheck.py @@ -138,6 +138,18 @@ def test_a_fragment_of_an_asset_is_reported(self): ], ) + def test_a_version_query_names_the_same_asset(self): + text = page('x') + self.assertEqual( + sitecheck.check({"index.html": text}, {"assets/a.svg"}), [] + ) + + def test_a_version_query_on_a_missing_asset_is_reported(self): + text = page('x') + self.assertEqual( + len(sitecheck.check({"index.html": text}, {"assets/a.svg"})), 2 + ) + def test_an_empty_id_attribute_is_not_a_target(self): text = page('x
      ') self.assertEqual(len(sitecheck.check({"index.html": text})), 1) diff --git a/tools/sitecheck.py b/tools/sitecheck.py index b3dfd9b..6800ac6 100644 --- a/tools/sitecheck.py +++ b/tools/sitecheck.py @@ -212,9 +212,13 @@ def from_site_origin(reference: str) -> str: def split_fragment(reference: str) -> tuple[str, str]: - """A reference as (path, fragment); either part may be empty""" + """A reference as (path, fragment); either part may be empty + + A query, such as the version that busts a browser's cache of + style.css?v=2026093001, names the same file and is dropped. + """ path, _, fragment = reference.partition("#") - return path, fragment + return path.partition("?")[0], fragment def check(