From 4fd36ba2f3f91da7258859808616078e3464fb97 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Sun, 17 Jun 2018 12:21:44 -0700 Subject: [PATCH] Work in progress --- datasette/app.py | 34 ++++++++++++++++++++++++++++++++++ datasette/views/base.py | 25 +++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/datasette/app.py b/datasette/app.py index 871a4bf1..e449dd89 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -16,6 +16,7 @@ from markupsafe import Markup import pluggy from jinja2 import ChoiceLoader, Environment, FileSystemLoader, PrefixLoader from sanic import Sanic, response +from sanic.request import Request as SanicRequest from sanic.exceptions import InvalidUsage, NotFound from .views.base import ( @@ -498,4 +499,37 @@ class Datasette: template = self.jinja_env.select_template(templates) return response.html(template.render(info), status=status) + class AsgiApp(): + def __init__(self, scope): + self.scope = scope + + async def __call__(self, receive, send): + # Create Sanic request from scope + path = self.scope["path"].encode("utf8") + if self.scope["query_string"]: + path = b"{}?{}".format(path, self.scope["query_string"]) + request = SanicRequest( + path, + {}, '1.1', 'GET', None + ) + async def write_callback(response): + await send({ + 'type': 'http.response.start', + 'status': 200, + 'headers': [ + [key.encode("utf-8"), value.encode("utf-8")] + for key, value in response.headers.items() + ], + }) + await send({ + 'type': 'http.response.body', + 'body': response.body, + }) + + # TODO: Fix this + stream_callback = write_callback + await app.handle_request(request, write_callback, stream_callback) + + app.AsgiApp = AsgiApp + return app diff --git a/datasette/views/base.py b/datasette/views/base.py index 36ef0540..ae1df581 100644 --- a/datasette/views/base.py +++ b/datasette/views/base.py @@ -143,6 +143,31 @@ class BaseView(RenderMixin): def get_templates(self, database, table=None): assert NotImplemented + async def asgi_get(self, receive, send): + kwargs = self.scope["url_route"]["kwargs"] + db_name = kwargs.pop("db_name") + name, hash, should_redirect = self.resolve_db_name(db_name, **kwargs) + qs = Querystring( + self.scope["path"], self.scope["query_string"].decode("utf-8") + ) + if should_redirect: + response = self.redirect(qs, should_redirect) + else: + response = await self.view_get(qs, name, hash, **kwargs) + # Send response over send() channel + await send({ + 'type': 'http.response.start', + 'status': 200, + 'headers': [ + [key.encode("utf-8"), value.encode("utf-8")] + for key, value in response.headers.items() + ], + }) + await send({ + 'type': 'http.response.body', + 'body': response.body, + }) + async def get(self, request, db_name, **kwargs): name, hash, should_redirect = self.resolve_db_name(db_name, **kwargs) qs = Querystring(request.path, request.query_string)