mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
datasette.client now applies base_url, closes #1026
This commit is contained in:
parent
7a67bc7a56
commit
84bc7244c1
5 changed files with 56 additions and 13 deletions
|
|
@ -44,6 +44,7 @@ from .url_builder import Urls
|
||||||
from .database import Database, QueryInterrupted
|
from .database import Database, QueryInterrupted
|
||||||
|
|
||||||
from .utils import (
|
from .utils import (
|
||||||
|
PrefixedUrlString,
|
||||||
async_call_with_supported_arguments,
|
async_call_with_supported_arguments,
|
||||||
await_me_maybe,
|
await_me_maybe,
|
||||||
call_with_supported_arguments,
|
call_with_supported_arguments,
|
||||||
|
|
@ -1242,9 +1243,12 @@ class NotFoundExplicit(NotFound):
|
||||||
|
|
||||||
class DatasetteClient:
|
class DatasetteClient:
|
||||||
def __init__(self, ds):
|
def __init__(self, ds):
|
||||||
|
self.ds = ds
|
||||||
self.app = ds.app()
|
self.app = ds.app()
|
||||||
|
|
||||||
def _fix(self, path):
|
def _fix(self, path):
|
||||||
|
if not isinstance(path, PrefixedUrlString):
|
||||||
|
path = self.ds.urls.path(path)
|
||||||
if path.startswith("/"):
|
if path.startswith("/"):
|
||||||
path = "http://localhost{}".format(path)
|
path = "http://localhost{}".format(path)
|
||||||
return path
|
return path
|
||||||
|
|
|
||||||
|
|
@ -387,9 +387,9 @@ class Response:
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def json(cls, body, status=200, headers=None):
|
def json(cls, body, status=200, headers=None, default=None):
|
||||||
return cls(
|
return cls(
|
||||||
json.dumps(body),
|
json.dumps(body, default=default),
|
||||||
status=status,
|
status=status,
|
||||||
headers=headers,
|
headers=headers,
|
||||||
content_type="application/json; charset=utf-8",
|
content_type="application/json; charset=utf-8",
|
||||||
|
|
|
||||||
|
|
@ -387,6 +387,18 @@ It offers the following methods:
|
||||||
``await datasette.client.request(method, path, **kwargs)`` - returns HTTPX Response
|
``await datasette.client.request(method, path, **kwargs)`` - returns HTTPX Response
|
||||||
Execute an internal request with the given HTTP method against that path.
|
Execute an internal request with the given HTTP method against that path.
|
||||||
|
|
||||||
|
These methods can be used with :ref:`internals_datasette_urls` - for example:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
table_json = (
|
||||||
|
await datasette.client.get(
|
||||||
|
datasette.urls.table("fixtures", "facetable", format="json")
|
||||||
|
)
|
||||||
|
).json()
|
||||||
|
|
||||||
|
``datasette.client`` methods automatically take the current :ref:`config_base_url` setting into account, whether or not you use the ``datasette.urls`` family of methods to construct the path.
|
||||||
|
|
||||||
For documentation on available ``**kwargs`` options and the shape of the HTTPX Response object refer to the `HTTPX Async documentation <https://www.python-httpx.org/async/>`__.
|
For documentation on available ``**kwargs`` options and the shape of the HTTPX Response object refer to the `HTTPX Async documentation <https://www.python-httpx.org/async/>`__.
|
||||||
|
|
||||||
.. _internals_datasette_urls:
|
.. _internals_datasette_urls:
|
||||||
|
|
|
||||||
|
|
@ -257,6 +257,9 @@ def register_routes():
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def asgi_scope(scope):
|
||||||
|
return Response.json(scope, default=repr)
|
||||||
|
|
||||||
return [
|
return [
|
||||||
(r"/one/$", one),
|
(r"/one/$", one),
|
||||||
(r"/two/(?P<name>.*)$", two),
|
(r"/two/(?P<name>.*)$", two),
|
||||||
|
|
@ -267,6 +270,7 @@ def register_routes():
|
||||||
(r"/not-async/$", not_async),
|
(r"/not-async/$", not_async),
|
||||||
(r"/add-message/$", add_message),
|
(r"/add-message/$", add_message),
|
||||||
(r"/render-message/$", render_message),
|
(r"/render-message/$", render_message),
|
||||||
|
(r"/asgi-scope$", asgi_scope),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,14 +31,37 @@ async def test_client_methods(datasette, method, path, expected_status):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_client_post(datasette):
|
@pytest.mark.parametrize("prefix", [None, "/prefix/"])
|
||||||
response = await datasette.client.post(
|
async def test_client_post(datasette, prefix):
|
||||||
"/-/messages",
|
original_base_url = datasette._config["base_url"]
|
||||||
data={
|
try:
|
||||||
"message": "A message",
|
if prefix is not None:
|
||||||
},
|
datasette._config["base_url"] = prefix
|
||||||
allow_redirects=False,
|
response = await datasette.client.post(
|
||||||
)
|
"/-/messages",
|
||||||
assert isinstance(response, httpx.Response)
|
data={
|
||||||
assert response.status_code == 302
|
"message": "A message",
|
||||||
assert "ds_messages" in response.cookies
|
},
|
||||||
|
allow_redirects=False,
|
||||||
|
)
|
||||||
|
assert isinstance(response, httpx.Response)
|
||||||
|
assert response.status_code == 302
|
||||||
|
assert "ds_messages" in response.cookies
|
||||||
|
finally:
|
||||||
|
datasette._config["base_url"] = original_base_url
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"prefix,expected_path", [(None, "/asgi-scope"), ("/prefix/", "/prefix/asgi-scope")]
|
||||||
|
)
|
||||||
|
async def test_client_path(datasette, prefix, expected_path):
|
||||||
|
original_base_url = datasette._config["base_url"]
|
||||||
|
try:
|
||||||
|
if prefix is not None:
|
||||||
|
datasette._config["base_url"] = prefix
|
||||||
|
response = await datasette.client.get("/asgi-scope")
|
||||||
|
path = response.json()["path"]
|
||||||
|
assert path == expected_path
|
||||||
|
finally:
|
||||||
|
datasette._config["base_url"] = original_base_url
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue