mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
Make custom pages compatible with base_url setting
Closes #1238 - base_url no longer causes custom page routing to fail - new route_path key in request.scope storing the path that was used for routing with the base_url prefix stripped - TestClient used by tests now avoids accidentally double processing of the base_url prefix
This commit is contained in:
parent
6e9b07be92
commit
a634121525
4 changed files with 27 additions and 8 deletions
|
|
@ -1089,6 +1089,7 @@ class DatasetteRouter:
|
||||||
base_url = self.ds.setting("base_url")
|
base_url = self.ds.setting("base_url")
|
||||||
if base_url != "/" and path.startswith(base_url):
|
if base_url != "/" and path.startswith(base_url):
|
||||||
path = "/" + path[len(base_url) :]
|
path = "/" + path[len(base_url) :]
|
||||||
|
scope = dict(scope, route_path=path)
|
||||||
request = Request(scope, receive)
|
request = Request(scope, receive)
|
||||||
# Populate request_messages if ds_messages cookie is present
|
# Populate request_messages if ds_messages cookie is present
|
||||||
try:
|
try:
|
||||||
|
|
@ -1143,9 +1144,8 @@ class DatasetteRouter:
|
||||||
await asgi_send_redirect(send, path.decode("latin1"))
|
await asgi_send_redirect(send, path.decode("latin1"))
|
||||||
else:
|
else:
|
||||||
# Is there a pages/* template matching this path?
|
# Is there a pages/* template matching this path?
|
||||||
template_path = (
|
route_path = request.scope.get("route_path", request.scope["path"])
|
||||||
os.path.join("pages", *request.scope["path"].split("/")) + ".html"
|
template_path = os.path.join("pages", *route_path.split("/")) + ".html"
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
template = self.ds.jinja_env.select_template([template_path])
|
template = self.ds.jinja_env.select_template([template_path])
|
||||||
except TemplateNotFound:
|
except TemplateNotFound:
|
||||||
|
|
@ -1153,7 +1153,7 @@ class DatasetteRouter:
|
||||||
if template is None:
|
if template is None:
|
||||||
# Try for a pages/blah/{name}.html template match
|
# Try for a pages/blah/{name}.html template match
|
||||||
for regex, wildcard_template in self.page_routes:
|
for regex, wildcard_template in self.page_routes:
|
||||||
match = regex.match(request.scope["path"])
|
match = regex.match(route_path)
|
||||||
if match is not None:
|
if match is not None:
|
||||||
context.update(match.groupdict())
|
context.update(match.groupdict())
|
||||||
template = wildcard_template
|
template = wildcard_template
|
||||||
|
|
@ -1356,8 +1356,8 @@ class DatasetteClient:
|
||||||
self.ds = ds
|
self.ds = ds
|
||||||
self.app = ds.app()
|
self.app = ds.app()
|
||||||
|
|
||||||
def _fix(self, path):
|
def _fix(self, path, avoid_path_rewrites=False):
|
||||||
if not isinstance(path, PrefixedUrlString):
|
if not isinstance(path, PrefixedUrlString) and not avoid_path_rewrites:
|
||||||
path = self.ds.urls.path(path)
|
path = self.ds.urls.path(path)
|
||||||
if path.startswith("/"):
|
if path.startswith("/"):
|
||||||
path = f"http://localhost{path}"
|
path = f"http://localhost{path}"
|
||||||
|
|
@ -1392,5 +1392,8 @@ class DatasetteClient:
|
||||||
return await client.delete(self._fix(path), **kwargs)
|
return await client.delete(self._fix(path), **kwargs)
|
||||||
|
|
||||||
async def request(self, method, path, **kwargs):
|
async def request(self, method, path, **kwargs):
|
||||||
|
avoid_path_rewrites = kwargs.pop("avoid_path_rewrites", None)
|
||||||
async with httpx.AsyncClient(app=self.app) as client:
|
async with httpx.AsyncClient(app=self.app) as client:
|
||||||
return await client.request(method, self._fix(path), **kwargs)
|
return await client.request(
|
||||||
|
method, self._fix(path, avoid_path_rewrites), **kwargs
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,7 @@ class TestClient:
|
||||||
method,
|
method,
|
||||||
path,
|
path,
|
||||||
allow_redirects=allow_redirects,
|
allow_redirects=allow_redirects,
|
||||||
|
avoid_path_rewrites=True,
|
||||||
cookies=cookies,
|
cookies=cookies,
|
||||||
headers=headers,
|
headers=headers,
|
||||||
content=post_body,
|
content=post_body,
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,19 @@ import pathlib
|
||||||
import pytest
|
import pytest
|
||||||
from .fixtures import make_app_client
|
from .fixtures import make_app_client
|
||||||
|
|
||||||
|
TEST_TEMPLATE_DIRS = str(pathlib.Path(__file__).parent / "test_templates")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def custom_pages_client():
|
def custom_pages_client():
|
||||||
|
with make_app_client(template_dir=TEST_TEMPLATE_DIRS) as client:
|
||||||
|
yield client
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def custom_pages_client_with_base_url():
|
||||||
with make_app_client(
|
with make_app_client(
|
||||||
template_dir=str(pathlib.Path(__file__).parent / "test_templates")
|
template_dir=TEST_TEMPLATE_DIRS, config={"base_url": "/prefix/"}
|
||||||
) as client:
|
) as client:
|
||||||
yield client
|
yield client
|
||||||
|
|
||||||
|
|
@ -23,6 +31,12 @@ def test_request_is_available(custom_pages_client):
|
||||||
assert "path:/request" == response.text
|
assert "path:/request" == response.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_custom_pages_with_base_url(custom_pages_client_with_base_url):
|
||||||
|
response = custom_pages_client_with_base_url.get("/prefix/request")
|
||||||
|
assert 200 == response.status
|
||||||
|
assert "path:/prefix/request" == response.text
|
||||||
|
|
||||||
|
|
||||||
def test_custom_pages_nested(custom_pages_client):
|
def test_custom_pages_nested(custom_pages_client):
|
||||||
response = custom_pages_client.get("/nested/nest")
|
response = custom_pages_client.get("/nested/nest")
|
||||||
assert 200 == response.status
|
assert 200 == response.status
|
||||||
|
|
|
||||||
|
|
@ -1523,6 +1523,7 @@ def test_base_url_config(app_client_base_url_prefix, path):
|
||||||
and href
|
and href
|
||||||
not in {
|
not in {
|
||||||
"https://datasette.io/",
|
"https://datasette.io/",
|
||||||
|
"https://github.com/simonw/datasette",
|
||||||
"https://github.com/simonw/datasette/blob/main/LICENSE",
|
"https://github.com/simonw/datasette/blob/main/LICENSE",
|
||||||
"https://github.com/simonw/datasette/blob/main/tests/fixtures.py",
|
"https://github.com/simonw/datasette/blob/main/tests/fixtures.py",
|
||||||
"/login-as-root", # Only used for the latest.datasette.io demo
|
"/login-as-root", # Only used for the latest.datasette.io demo
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue