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

.db downloads should be served with an ETag #1739

Closed
simonw opened this issue May 3, 2022 · 6 comments
Closed

.db downloads should be served with an ETag #1739

simonw opened this issue May 3, 2022 · 6 comments

Comments

@simonw
Copy link
Owner

simonw commented May 3, 2022

I noticed that my Pyodide Datasette prototype is downloading the same database file every single time rather than browser caching it:

image

@simonw
Copy link
Owner Author

simonw commented May 3, 2022

@simonw
Copy link
Owner Author

simonw commented May 3, 2022

Reminded myself how this works by reviewing conditional-get: https://github.com/simonw/conditional-get/blob/db6dfec0a296080aaf68fcd80e55fb3f0714e738/conditional_get/cli.py#L33-L52

Simply add a If-None-Match: last-known-etag header to the request and check that the response is a status 304 with an empty body.

@simonw
Copy link
Owner Author

simonw commented May 3, 2022

Database downloads are served here:

headers["Transfer-Encoding"] = "chunked"
return AsgiFileDownload(
filepath,
filename=os.path.basename(filepath),
content_type="application/octet-stream",
headers=headers,
)

Here's AsgiFileDownload:

class AsgiFileDownload:
def __init__(
self,
filepath,
filename=None,
content_type="application/octet-stream",
headers=None,
):
self.headers = headers or {}
self.filepath = filepath
self.filename = filename
self.content_type = content_type
async def asgi_send(self, send):
return await asgi_send_file(
send,
self.filepath,
filename=self.filename,
content_type=self.content_type,
headers=self.headers,
)

I can add an etag= parameter to that and populate it with db.hash, if it is populated (which it always should be for immutable databases that can be downloaded).

@simonw
Copy link
Owner Author

simonw commented May 3, 2022

Relevant tests start here:

def test_database_download_for_immutable():

@simonw
Copy link
Owner Author

simonw commented May 3, 2022

That worked - both DBs are 304 for me now on a subsequent load of the page:

CleanShot 2022-05-03 at 08 11 05@2x

@simonw
Copy link
Owner Author

simonw commented May 4, 2022

That prototype is now public: https://github.com/simonw/datasette-lite

simonw added a commit that referenced this issue Jul 18, 2022
simonw added a commit that referenced this issue Aug 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant