]> git.ipfire.org Git - thirdparty/starlette.git/commitdiff
Ignore `if-modified-since` if `if-none-match` is present (#3057)
authorMarcelo Trylesinski <marcelotryle@gmail.com>
Sat, 1 Nov 2025 11:17:34 +0000 (12:17 +0100)
committerGitHub <noreply@github.com>
Sat, 1 Nov 2025 11:17:34 +0000 (11:17 +0000)
Co-authored-by: Smixi-syn <200990126+Smixi-syn@users.noreply.github.com>
Co-authored-by: grindhold <2592640+grindhold@users.noreply.github.com>
starlette/staticfiles.py
tests/test_staticfiles.py

index 7fba9aa95b51787f848e9a7be2bff1c7a85ab5c1..a458fd7d8aa5d1cd61add58fd4c65588fff220ec 100644 (file)
@@ -201,13 +201,10 @@ class StaticFiles:
         Given the request and response headers, return `True` if an HTTP
         "Not Modified" response could be returned instead.
         """
-        try:
-            if_none_match = request_headers["if-none-match"]
+        if if_none_match := request_headers.get("if-none-match"):
+            # The "etag" header is added by FileResponse, so it's always present.
             etag = response_headers["etag"]
-            if etag in [tag.strip(" W/") for tag in if_none_match.split(",")]:
-                return True
-        except KeyError:
-            pass
+            return etag in [tag.strip(" W/") for tag in if_none_match.split(",")]
 
         try:
             if_modified_since = parsedate(request_headers["if-modified-since"])
index dfeb09ebde6fe95cbd4dbf61c221bae1cc1cf9d9..1bf53ff9ca5a9c3a353a3dbc7efef2d0f407d247 100644 (file)
@@ -231,6 +231,24 @@ def test_staticfiles_200_with_etag_mismatch(tmpdir: Path, test_client_factory: T
     assert second_resp.content == b"<file content>"
 
 
+def test_staticfiles_200_with_etag_mismatch_and_timestamp_match(
+    tmpdir: Path, test_client_factory: TestClientFactory
+) -> None:
+    path = tmpdir / "example.txt"
+    path.write_text("<file content>", encoding="utf-8")
+
+    app = StaticFiles(directory=tmpdir)
+    client = test_client_factory(app)
+    first_resp = client.get("/example.txt")
+    assert first_resp.status_code == 200
+    assert first_resp.headers["etag"] != '"123"'
+    last_modified = first_resp.headers["last-modified"]
+    # If `if-none-match` is present, `if-modified-since` is ignored.
+    second_resp = client.get("/example.txt", headers={"if-none-match": '"123"', "if-modified-since": last_modified})
+    assert second_resp.status_code == 200
+    assert second_resp.content == b"<file content>"
+
+
 def test_staticfiles_304_with_last_modified_compare_last_req(
     tmpdir: Path, test_client_factory: TestClientFactory
 ) -> None: