You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
and datasette works correctly. However, if you view a query and then click on the 'This data as json, CSV' both links omit the base_url prefix and are therefore 404.
base_url has been a source of so many bugs like this! I often find them quite hard to replicate, likely because I haven't made myself a good Apache mod_proxy testing environment yet.
Having a live demo running on Cloud Run that proxies through Apache and uses base_url would be incredibly useful for replicating and debugging this kind of thing. I wonder how hard it is to run Apache and mod_proxy in the same Docker container as Datasette?
And then hit http://localhost:5000/foo/bar/fixtures?sql=select+*+from+compound_three_primary_keys+limit+1&_context=1 to view the template context - and it showed the bug, output edited to just show relevant keys:
That explains the bug - that request doesn't maintain the original path prefix of http://localhost:5000/foo/bar/fixtures?sql= (also it's been rewritten to localhost:9000 instead of localhost:5000).
In the meantime I can catch these errors by changing the test to run each path twice, once with and once without the prefix. This should accurately simulate how Apache is working here.
In the meantime I can catch these errors by changing the test to run each path twice, once with and once without the prefix. This should accurately simulate how Apache is working here.
This worked, I managed to get the tests to fail! Here's the change I made:
diff --git a/tests/test_html.py b/tests/test_html.py
index f24165b..dbdfe59 100644
--- a/tests/test_html.py+++ b/tests/test_html.py@@ -1614,12 +1614,19 @@ def test_metadata_sort_desc(app_client):
"/fixtures/compound_three_primary_keys/a,a,a",
"/fixtures/paginated_view",
"/fixtures/facetable",
+ "/fixtures?sql=select+1",
],
)
-def test_base_url_config(app_client_base_url_prefix, path):+@pytest.mark.parametrize("use_prefix", (True, False))+def test_base_url_config(app_client_base_url_prefix, path, use_prefix):
client = app_client_base_url_prefix
- response = client.get("/prefix/" + path.lstrip("/"))+ path_to_get = path+ if use_prefix:+ path_to_get = "/prefix/" + path.lstrip("/")+ response = client.get(path_to_get)
soup = Soup(response.body, "html.parser")
+ if path == "/fixtures?sql=select+1":+ assert False
for el in soup.findAll(["a", "link", "script"]):
if "href" in el.attrs:
href = el["href"]
@@ -1642,11 +1649,12 @@ def test_base_url_config(app_client_base_url_prefix, path):
# If this has been made absolute it may start http://localhost/
if href.startswith("http://localhost/"):
href = href[len("http://localost/") :]
- assert href.startswith("/prefix/"), {+ assert href.startswith("/prefix/"), json.dumps({
"path": path,
+ "path_to_get": path_to_get,
"href_or_src": href,
"element_parent": str(el.parent),
- }+ }, indent=4, default=repr)
def test_base_url_affects_metadata_extra_css_urls(app_client_base_url_prefix):
I think what's happening here is Apache is actually making a request to /fixtures rather than making a request to /prefix/fixtures - and Datasette is replying to requests on both the prefixed and the non-prefixed paths.
This is pretty confusing! I think Datasette should ONLY reply to /prefix/fixtures instead and return a 404 for /fixtures - this would make things a whole lot easier to debug.
But shipping that change could break existing deployments. Maybe that should be a breaking change for 1.0.
On further thought I'm not going to do this. Having Datasette work behind a proxy the way it does right now is clearly easy for people to deploy (now that I've fixed the bugs) and I trust my improved tests to catch problems in the future.
thanks so very much for the prompt attention and fix! Plus, the animated GIF showing the bug is just extra and I love it. Interactions like this are why I love open source.
Activity
simonw commentedon Nov 19, 2021
base_urlhas been a source of so many bugs like this! I often find them quite hard to replicate, likely because I haven't made myself a good Apachemod_proxytesting environment yet.simonw commentedon Nov 19, 2021
Having a live demo running on Cloud Run that proxies through Apache and uses
base_urlwould be incredibly useful for replicating and debugging this kind of thing. I wonder how hard it is to run Apache andmod_proxyin the same Docker container as Datasette?simonw commentedon Nov 19, 2021
I now have a
Dockerfilein #1521 (comment) that I can use to run a local Apache 2 withmod_proxyto investigate this class of bugs!simonw commentedon Nov 19, 2021
Bug confirmed:
simonw commentedon Nov 19, 2021
The relevant test is this one:
datasette/tests/test_html.py
Lines 1608 to 1649 in 3025505
I modified that test to add
"/fixtures/facetable?sql=select+1"as one of the tested paths, and dropped in anassert Falseto pause it in the debugger:BUT... in the debugger:
Those all have the correct prefix! But that's not what I'm seeing in my
Dockerfilereproduction of the issue.Something very weird is going on here.
simonw commentedon Nov 19, 2021
I added
template_debugin the Dockerfile:And then hit
http://localhost:5000/foo/bar/fixtures?sql=select+*+from+compound_three_primary_keys+limit+1&_context=1to view the template context - and it showed the bug, output edited to just show relevant keys:{ "edit_sql_url": "/foo/bar/fixtures?sql=select+%2A+from+compound_three_primary_keys+limit+1", "settings": { "force_https_urls": false, "template_debug": true, "trace_debug": false, "base_url": "/foo/bar/" }, "show_hide_link": "/fixtures?sql=select+%2A+from+compound_three_primary_keys+limit+1&_context=1&_hide_sql=1", "show_hide_text": "hide", "show_hide_hidden": "", "renderers": { "json": "/fixtures.json?sql=select+*+from+compound_three_primary_keys+limit+1&_context=1" }, "url_csv": "/fixtures.csv?sql=select+*+from+compound_three_primary_keys+limit+1&_context=1&_size=max", "url_csv_path": "/fixtures.csv", "base_url": "/foo/bar/" }This is so strange.
edit_sql_urlandbase_urlare correct, butshow_hide_linkandurl_csvandrenderers.jsonare not.And it's really strange that the bug doesn't show up in the tests.
simonw commentedon Nov 19, 2021
Here's the code that generates
edit_sql_urlcorrectly:datasette/datasette/views/database.py
Lines 416 to 420 in 8584993
And here's the code for
show_hide_link:datasette/datasette/views/database.py
Lines 432 to 433 in 8584993
And for
url_csv:datasette/datasette/views/base.py
Lines 600 to 602 in 8584993
simonw commentedon Nov 19, 2021
The implementations of
path_with_removed_argsandpath_with_format:datasette/datasette/utils/__init__.py
Lines 228 to 254 in 8584993
datasette/datasette/utils/__init__.py
Lines 710 to 729 in 8584993
simonw commentedon Nov 19, 2021
In the
?_context=debug view the request looks like this:I'm going to add a
repr()to it such that it's a bit more useful.repr() method for Request, refs #1519
simonw commentedon Nov 19, 2021
Modified my
Dockerfileto do this:And now the
requestin that debug?_context=1looks like this:That explains the bug - that request doesn't maintain the original path prefix of
http://localhost:5000/foo/bar/fixtures?sql=(also it's been rewritten tolocalhost:9000instead oflocalhost:5000).simonw commentedon Nov 19, 2021
Still not clear why the tests pass but the live example fails.
3 remaining items
simonw commentedon Nov 19, 2021
In the meantime I can catch these errors by changing the test to run each path twice, once with and once without the prefix. This should accurately simulate how Apache is working here.
Fixed test I broke with new repr() in ##1519
simonw commentedon Nov 20, 2021
Thanks to #1522 I have a live demo that exhibits this bug now: https://apache-proxy-demo.datasette.io/prefix/fixtures/attraction_characteristic
simonw commentedon Nov 20, 2021
This worked, I managed to get the tests to fail! Here's the change I made:
simonw commentedon Nov 20, 2021
Adding that test found (I hope!) all of the remaining
base_urlbugs. There were a bunch! I think I finally get to close #838 too.Fixed a whole bunch of broken base_url links
simonw commentedon Nov 20, 2021
Ouch a nasty bug crept through there - https://datasette-apache-proxy-demo-j7hipcg4aq-uc.a.run.app/prefix/fixtures/compound_three_primary_keys says
Fixed bug introduced in #1519
Fix more broken base_url links
Hopefully last fix relating to #1519, #838
simonw commentedon Nov 20, 2021
OK, i think I got all of them this time!
The latest demo is now live at https://datasette-apache-proxy-demo.fly.dev/prefix/fixtures/sortable?_facet=pk2
I'm closing this issue, but feel free to re-open it if you spot any that I missed.
simonw commentedon Nov 20, 2021
On further thought I'm not going to do this. Having Datasette work behind a proxy the way it does right now is clearly easy for people to deploy (now that I've fixed the bugs) and I trust my improved tests to catch problems in the future.
Release 0.59.3
phubbard commentedon Dec 1, 2021
thanks so very much for the prompt attention and fix! Plus, the animated GIF showing the bug is just extra and I love it. Interactions like this are why I love open source.