StaticFiles: Fix cache validation bug for deleted files in html mode (#1023)

* StaticFiles: Fix cache validation bug for deleted files in html mode

Previously StaticFiles would return 304 for a deleted file if its
Last-Modified date was the same as that of 404.html

* Use black formatter

Co-authored-by: Jamie Hewland <jhewland@gmail.com>
This commit is contained in:
ilunev 2021-02-05 23:15:25 +03:00 committed by GitHub
parent 32745944b0
commit 0ac60bbeb2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 2 deletions

View File

@ -134,8 +134,11 @@ class StaticFiles:
# Check for '404.html' if we're in HTML mode.
full_path, stat_result = await self.lookup_path("404.html")
if stat_result is not None and stat.S_ISREG(stat_result.st_mode):
return self.file_response(
full_path, stat_result, scope, status_code=404
return FileResponse(
full_path,
stat_result=stat_result,
method=scope["method"],
status_code=404,
)
return PlainTextResponse("Not Found", status_code=404)

View File

@ -243,3 +243,40 @@ def test_staticfiles_html(tmpdir):
response = client.get("/missing")
assert response.status_code == 404
assert response.text == "<h1>Custom not found page</h1>"
def test_staticfiles_cache_invalidation_for_deleted_file_html_mode(tmpdir):
path_404 = os.path.join(tmpdir, "404.html")
with open(path_404, "w") as file:
file.write("<p>404 file</p>")
path_some = os.path.join(tmpdir, "some.html")
with open(path_some, "w") as file:
file.write("<p>some file</p>")
common_modified_time = time.mktime(
time.strptime("2013-10-10 23:40:00", "%Y-%m-%d %H:%M:%S")
)
os.utime(path_404, (common_modified_time, common_modified_time))
os.utime(path_some, (common_modified_time, common_modified_time))
app = StaticFiles(directory=tmpdir, html=True)
client = TestClient(app)
resp_exists = client.get("/some.html")
assert resp_exists.status_code == 200
assert resp_exists.text == "<p>some file</p>"
resp_cached = client.get(
"/some.html",
headers={"If-Modified-Since": resp_exists.headers["last-modified"]},
)
assert resp_cached.status_code == 304
os.remove(path_some)
resp_deleted = client.get(
"/some.html",
headers={"If-Modified-Since": resp_exists.headers["last-modified"]},
)
assert resp_deleted.status_code == 404
assert resp_deleted.text == "<p>404 file</p>"