-
-
Notifications
You must be signed in to change notification settings - Fork 771
Port Datasette from Sanic to ASGI + Uvicorn #518
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
Conversation
Lots still to do: * Static files are not being served * Streaming CSV files don't work * Tests all fail * Some URLs (e.g. the 'next' link on tables) are incorrect But... the server does start up and you can browse databases/tables
CSV tests still all fail. Also I marked test_trace() as skip because I have not yet re-implemented trace.
Not yet using aiofiles so will not correctly handle larger static assets. Still needs security tightening. Still needs tests. But the CSS and JS now work
Mainly so you can tell if a Datasette instance is running on ASGI or not.
Refactored utils.py into a datasette/utils package, refactored some of the ASGI helper code into datasette/utils/asgi.py
All of the tests now pass
This is strange: on my local machine Lines 721 to 727 in d60fbfc
|
Mystery solved: that's because I'm constructing my own scope object and testing via Lines 42 to 57 in d60fbfc
I don't want to introduce the complexity of launching a real Uvicorn as part of the tests, so I guess I'll have to carefully update my |
This causes tests to fail.
Weird new bug: http://127.0.0.1:8001/fixtures/table%2Fwith%2Fslashes.csv?_format=json is downloading CSV for me now. https://latest.datasette.io/fixtures/table%2Fwith%2Fslashes.csv?_format=json does the right thing. |
Another bug: JSON is being served without a content-type header:
|
OK, for Get ?_trace=1 working again. The old code lives in two places: Lines 546 to 560 in 35429f9
And then: Lines 653 to 672 in 35429f9
So it's stashing something on the request to tell the rest of the code it should be tracing, then using that collected data from the request to add information to the final body. One possible shape for the replacement is a new ASGI middleware that wraps everything else. We don't have a mutable request object here though, so we will need to untangle this entirely from the request object. Also tricky is that in ASGI land we handle streams - we don't usually wait around for the entire response body to be compiled for us. This means the code that modifies the response (adding to the JSON or appending inside the As usual, Starlette seems to have figured this out: https://github.com/encode/starlette/blob/8c8cc2ec0a5cb834a9a15b871ae8b480503abb67/starlette/middleware/gzip.py |
Replacement for @app.listener("before_server_start") - this is what the ASGI lifespan protocol is for. I know Uvicorn supports this because it keeps saying I think the solution here will be to introduce another ASGI wrapper class similar to |
Also did a little bit of lint cleanup
The big one: Replace Sanic request and response objects with my own classes, so I can remove Sanic dependency |
The I'm going to replace it with specific handling for HEAD requests plus a unit test. |
The Sanic stuff I import at the moment is:
|
For the request object.... what are the fields of it I actually use?
ALL of those are things that can be derived from the |
Last thing is to replace
Implementations here: https://github.com/huge-success/sanic/blob/0.7.0/sanic/response.py#L175-L285 |
It's live! https://a559123.datasette.io/ |
Most of the code here was fleshed out in comments on #272 (Port Datasette to ASGI) - this pull request will track the final pieces:
raw_path
issueraw_path
so table names containing/
can work correctly@app.listener("before_server_start")
/fixtures/table%2Fwith%2Fslashes.csv?_format=json
downloads as CSV