Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 3 commits into from Feb 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 5 additions & 2 deletions starlette/staticfiles.py
Expand Up @@ -134,8 +134,11 @@ async def get_response(self, path: str, scope: Scope) -> Response:
# 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)
Expand Down
37 changes: 37 additions & 0 deletions tests/test_staticfiles.py
Expand Up @@ -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>"