From 213e6a892636408d289dd75511327c4312c438e4 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Tue, 21 Jul 2020 21:52:35 -0700 Subject: [PATCH] content-length for DB downloads, closes #905 --- datasette/utils/asgi.py | 2 ++ tests/test_html.py | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/datasette/utils/asgi.py b/datasette/utils/asgi.py index bf8461f8..7caa3469 100644 --- a/datasette/utils/asgi.py +++ b/datasette/utils/asgi.py @@ -7,6 +7,7 @@ from html import escape from http.cookies import SimpleCookie, Morsel import re import aiofiles +import aiofiles.os # Workaround for adding samesite support to pre 3.8 python Morsel._reserved["samesite"] = "SameSite" @@ -252,6 +253,7 @@ async def asgi_send_file( if filename: headers["Content-Disposition"] = 'attachment; filename="{}"'.format(filename) first = True + headers["content-length"] = str((await aiofiles.os.stat(str(filepath))).st_size) async with aiofiles.open(str(filepath), mode="rb") as fp: if first: await asgi_start( diff --git a/tests/test_html.py b/tests/test_html.py index ebd91cf1..e3d3c2fc 100644 --- a/tests/test_html.py +++ b/tests/test_html.py @@ -898,7 +898,7 @@ def test_table_metadata(app_client): assert_footer_links(soup) -def test_database_download_allowed_for_immutable(): +def test_database_download_for_immutable(): with make_app_client(is_immutable=True) as client: assert not client.ds.databases["fixtures"].is_mutable # Regular page should have a download link @@ -906,7 +906,13 @@ def test_database_download_allowed_for_immutable(): soup = Soup(response.body, "html.parser") assert len(soup.findAll("a", {"href": re.compile(r"\.db$")})) # Check we can actually download it - assert 200 == client.get("/fixtures.db").status + download_response = client.get("/fixtures.db") + assert 200 == download_response.status + # Check the content-length header exists + assert "content-length" in download_response.headers + content_length = download_response.headers["content-length"] + assert content_length.isdigit() + assert int(content_length) > 100 def test_database_download_disallowed_for_mutable(app_client):