await Request(scope, receive).post_vars() method, closes #700

Needed for #698
This commit is contained in:
Simon Willison 2020-03-16 19:47:37 -07:00
commit a000c80d50
2 changed files with 37 additions and 4 deletions

View file

@ -1,7 +1,7 @@
import json
from datasette.utils import RequestParameters
from mimetypes import guess_type
from urllib.parse import parse_qs, urlunparse
from urllib.parse import parse_qs, urlunparse, parse_qsl
from pathlib import Path
from html import escape
import re
@ -13,8 +13,9 @@ class NotFound(Exception):
class Request:
def __init__(self, scope):
def __init__(self, scope, receive):
self.scope = scope
self.receive = receive
@property
def method(self):
@ -66,6 +67,18 @@ class Request:
def raw_args(self):
return {key: value[0] for key, value in self.args.items()}
async def post_vars(self):
body = []
body = b""
more_body = True
while more_body:
message = await self.receive()
assert message["type"] == "http.request", message
body += message.get("body", b"")
more_body = message.get("more_body", False)
return dict(parse_qsl(body.decode("utf-8")))
@classmethod
def fake(cls, path_with_query_string, method="GET", scheme="http"):
"Useful for constructing Request objects for tests"
@ -79,7 +92,7 @@ class Request:
"scheme": scheme,
"type": "http",
}
return cls(scope)
return cls(scope, None)
class AsgiRouter:
@ -171,7 +184,7 @@ class AsgiView:
# that were already tucked into scope["url_route"]["kwargs"] by
# the router, similar to how Django Channels works:
# https://channels.readthedocs.io/en/latest/topics/routing.html#urlrouter
request = Request(scope)
request = Request(scope, receive)
self = view.view_class(*class_args, **class_kwargs)
response = await self.dispatch_request(
request, **scope["url_route"]["kwargs"]