Started trying to get --asgi mode working

This commit is contained in:
Simon Willison 2018-07-07 19:58:00 -07:00
commit 13ed3069f2
No known key found for this signature in database
GPG key ID: 17E2DEA2588B7F52
3 changed files with 55 additions and 1 deletions

View file

@ -430,6 +430,12 @@ class Datasette:
self.executor, sql_operation_in_thread
)
def asgi_app(self):
from starlette import Router, Path
return Router([
Path('/', app=IndexView(self).asgi_app(), methods=['GET']),
])
def app(self):
app = Sanic(__name__)
default_templates = str(app_root / "datasette" / "templates")

View file

@ -256,6 +256,9 @@ def package(
"-h", "--host", default="127.0.0.1", help="host for server, defaults to 127.0.0.1"
)
@click.option("-p", "--port", default=8001, help="port for server, defaults to 8001")
@click.option(
"--asgi", is_flag=True, help="Run in ASGI mode"
)
@click.option(
"--debug", is_flag=True, help="Enable debug mode - useful for development"
)
@ -316,6 +319,7 @@ def serve(
files,
host,
port,
asgi,
debug,
reload,
cors,
@ -372,4 +376,9 @@ def serve(
)
# Force initial hashing/table counting
ds.inspect()
ds.app().run(host=host, port=port, debug=debug)
if asgi:
from uvicorn.run import UvicornServer
app = ds.asgi_app()
UvicornServer().run(app, host=host, port=port)
else:
ds.app().run(host=host, port=port, debug=debug)

View file

@ -12,6 +12,8 @@ from sanic import response
from sanic.exceptions import NotFound
from sanic.views import HTTPMethodView
from starlette import asgi_application, Response
from datasette import __version__
from datasette.utils import (
CustomJSONEncoder,
@ -43,8 +45,45 @@ class DatasetteError(Exception):
self.messagge_is_html = messagge_is_html
class RequestWrapper:
# Implements the subset of the Sanic request that my code uses
def __init__(self, starlette_request):
self._request = starlette_request
@property
def path(self):
return self._request.url.path
@property
def query_string(self):
return str(self._request.query_string)
@property
def args(self):
# Key/list-of-values
# There's probably a better way to do this:
d = {}
for key, value in self._request.query_string:
d.setdefault(key, []).append(value)
return d
@property
def raw_args(self):
# Flat key/first-value dictionary
return self._request.query_string._dict
class RenderMixin(HTTPMethodView):
def asgi_app(self):
@asgi_application
async def app(request):
sanic_response = await self.get(
RequestWrapper(request), **request["kwargs"]
)
return Response(sanic_response.body)
return app
def render(self, templates, **context):
template = self.ds.jinja_env.select_template(templates)
select_templates = [