57 lines
2.0 KiB
Python
57 lines
2.0 KiB
Python
![]() |
from urllib.parse import unquote, urlparse
|
||
|
|
||
|
from asgiref.testing import ApplicationCommunicator
|
||
|
|
||
|
|
||
|
class HttpCommunicator(ApplicationCommunicator):
|
||
|
"""
|
||
|
ApplicationCommunicator subclass that has HTTP shortcut methods.
|
||
|
|
||
|
It will construct the scope for you, so you need to pass the application
|
||
|
(uninstantiated) along with HTTP parameters.
|
||
|
|
||
|
This does not support full chunking - for that, just use ApplicationCommunicator
|
||
|
directly.
|
||
|
"""
|
||
|
|
||
|
def __init__(self, application, method, path, body=b"", headers=None):
|
||
|
parsed = urlparse(path)
|
||
|
self.scope = {
|
||
|
"type": "http",
|
||
|
"http_version": "1.1",
|
||
|
"method": method.upper(),
|
||
|
"path": unquote(parsed.path),
|
||
|
"query_string": parsed.query.encode("utf-8"),
|
||
|
"headers": headers or [],
|
||
|
}
|
||
|
assert isinstance(body, bytes)
|
||
|
self.body = body
|
||
|
self.sent_request = False
|
||
|
super().__init__(application, self.scope)
|
||
|
|
||
|
async def get_response(self, timeout=1):
|
||
|
"""
|
||
|
Get the application's response. Returns a dict with keys of
|
||
|
"body", "headers" and "status".
|
||
|
"""
|
||
|
# If we've not sent the request yet, do so
|
||
|
if not self.sent_request:
|
||
|
self.sent_request = True
|
||
|
await self.send_input({"type": "http.request", "body": self.body})
|
||
|
# Get the response start
|
||
|
response_start = await self.receive_output(timeout)
|
||
|
assert response_start["type"] == "http.response.start"
|
||
|
# Get all body parts
|
||
|
response_start["body"] = b""
|
||
|
while True:
|
||
|
chunk = await self.receive_output(timeout)
|
||
|
assert chunk["type"] == "http.response.body"
|
||
|
assert isinstance(chunk["body"], bytes)
|
||
|
response_start["body"] += chunk["body"]
|
||
|
if not chunk.get("more_body", False):
|
||
|
break
|
||
|
# Return structured info
|
||
|
del response_start["type"]
|
||
|
response_start.setdefault("headers", [])
|
||
|
return response_start
|