diff --git a/datasette/app.py b/datasette/app.py index 20aae7d09e..2f74cbbebf 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -4,6 +4,7 @@ import datetime import glob import hashlib +import httpx import inspect import itertools from itsdangerous import BadSignature @@ -312,6 +313,7 @@ def __init__( self._register_renderers() self._permission_checks = collections.deque(maxlen=200) self._root_token = secrets.token_hex(32) + self.client = DatasetteClient(self) async def invoke_startup(self): for hook in pm.hook.startup(datasette=self): @@ -1209,3 +1211,34 @@ def route_pattern_from_filepath(filepath): class NotFoundExplicit(NotFound): pass + + +class DatasetteClient: + def __init__(self, ds): + self._client = httpx.AsyncClient(app=ds.app()) + + def _fix(self, path): + if path.startswith("/"): + path = "http://localhost{}".format(path) + return path + + async def get(self, path, **kwargs): + return await self._client.get(self._fix(path), **kwargs) + + async def options(self, path, **kwargs): + return await self._client.options(self._fix(path), **kwargs) + + async def head(self, path, **kwargs): + return await self._client.head(self._fix(path), **kwargs) + + async def post(self, path, **kwargs): + return await self._client.post(self._fix(path), **kwargs) + + async def put(self, path, **kwargs): + return await self._client.put(self._fix(path), **kwargs) + + async def patch(self, path, **kwargs): + return await self._client.patch(self._fix(path), **kwargs) + + async def delete(self, path, **kwargs): + return await self._client.delete(self._fix(path), **kwargs) diff --git a/setup.py b/setup.py index ddcd8106c4..f63f87ef89 100644 --- a/setup.py +++ b/setup.py @@ -49,6 +49,7 @@ def get_version(): "click-default-group~=1.2.2", "Jinja2>=2.10.3,<2.12.0", "hupper~=1.9", + "httpx~=0.15", "pint~=0.9", "pluggy~=0.13.0", "uvicorn~=0.11",