-
-
Notifications
You must be signed in to change notification settings - Fork 700
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Table+query JSON and CSV links broken when using base_url
setting
#1590
Comments
Thanks for the steps to reproduce - I have your bug running on my laptop now. I've been mostly testing this stuff using the hosted copy of Datasette here, which doesn't exhibit the bug: https://datasette-apache-proxy-demo.fly.dev/prefix/fixtures?sql=select+sqlite_version%28%29 Something interesting definitely going on here! |
I'm using the https://datasette.io/plugins/datasette-debug-asgi plugin to investigate. On my laptop using Daphne I get this: http://127.0.0.1:8032/datasettes/-/asgi-scope
On the demo running on Fly (which I just redeployed with that plugin) I get this: https://datasette-apache-proxy-demo.fly.dev/prefix/-/asgi-scope
The version that works as |
The Daphne one has this key: Maybe Datasette's routing code needs to look out for that, if it's available, and use it to reconstruct the requested path? The code in question is here: Lines 1143 to 1149 in 8c401ee
|
Oh wait! It looks like Yup, I added it in a634121 - commit message says:
So actually part of the mystery here is: why does the Fly hosted one NOT have that key? |
Looking closer at the code quoted above, it doesn't modify |
Thank you for the quick reply! Just a quick observation, I am running this locally without a proxy, whereas your fly example seems to be running behind an apache proxy (if the name is accurate). Can it be that the apache proxy strips the prefix before it passes on the request to the daphne backend? |
In my example, path matching happens at the application layer (being the Django channels URLRouter). That might be a somewhat exotic solution that would normally be solved by a proxy like Apache or Nginx. However, in my specific use case, this is a "feature" enabling me to do simple management of databases and metadata from within a Django admin app instance mapped in that same router. |
Seeing as this area of the code has produced so many bugs in the past, I think part of the fix may be to write comprehensive documentation about how routing works for the internals documentation. Doing so might help me figure this bug out! |
Since this is a special case bug for when using Datasette as a library I wonder if a good fix here would be to support something like this: application = URLRouter([
re_path(r"^datasettes/.*", asgi_cors(datasette_.app(remove_path_prefix="datasettes/"), allow_all=True)),
]) |
I think this prefixed string mechanism is supposed to prevent the datasette/datasette/url_builder.py Lines 9 to 16 in 3664ddd
But with a bit of extra logging all of the inputs to that are NOT prefixed strings:
So it looks like |
OK, I'm going to recommend a workaround for this instead. Here's import pathlib
from asgi_cors import asgi_cors
from channels.routing import URLRouter
from django.urls import re_path
from datasette.app import Datasette
def rewrite_path(app, prefix_to_strip):
async def rewrite_path_app(scope, receive, send):
if (
scope["type"] == "http"
and "path" in scope
and scope["path"].startswith(prefix_to_strip)
):
scope["path"] = scope["path"][len(prefix_to_strip) :]
if "raw_path" in scope:
scope["raw_path"] = scope["raw_path"][len(prefix_to_strip) :]
await app(scope, receive, send)
return rewrite_path_app
datasette_ = Datasette(
files=["fixtures.db"],
settings={"base_url": "/datasettes/", "plugins": {}},
)
application = URLRouter(
[
re_path(
r"^datasettes/.*",
asgi_cors(rewrite_path(datasette_.app(), "/datasettes"), allow_all=True),
),
]
) This works on my laptop - please re-open the ticket if it doesn't work for you! |
Datasette appends the prefix found in the
base_url
setting twice if abase_url
is set.In the follow asgi example, I'm hosting a custom Datasette instance:
Running it with:
Using a simple query on the
_memory
table:select sqlite_version()
http://localhost:8002/datasettes/_memory?sql=select+sqlite_version%28%29
It renders the following upon inspection:
I am using datasette version
0.59.4
The text was updated successfully, but these errors were encountered: