html_url,issue_url,id,node_id,user,created_at,updated_at,author_association,body,reactions,issue,performed_via_github_app
https://github.com/simonw/datasette/issues/1590#issuecomment-1012661522,https://api.github.com/repos/simonw/datasette/issues/1590,1012661522,IC_kwDOBm6k_c48W_0S,9599,2022-01-14T01:16:08Z,2022-01-14T01:16:34Z,OWNER,"OK, I'm going to recommend a workaround for this instead. Here's `asgi.py` updated to strip the prefix before passing the request on to Datasette:
```python
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!","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1099723916,
https://github.com/simonw/datasette/issues/1590#issuecomment-1012656790,https://api.github.com/repos/simonw/datasette/issues/1590,1012656790,IC_kwDOBm6k_c48W-qW,9599,2022-01-14T01:05:34Z,2022-01-14T01:05:34Z,OWNER,"I think this prefixed string mechanism is supposed to prevent the `base_url` prefix from being applied twice: https://github.com/simonw/datasette/blob/3664ddd400062123e99500d28b160c7944408c1a/datasette/url_builder.py#L9-L16
But with a bit of extra logging all of the inputs to that are NOT prefixed strings:
```
Urls.path called with: /datasettes/fixtures/compound_three_primary_keys?_sort=content (PrefixedUrlString = False)
returning /datasettes/datasettes/fixtures/compound_three_primary_keys?_sort=content
```
So it looks like `urls.path(...)` is indeed the code responsible for doubling up that `/datasettes/` prefix.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1099723916,
https://github.com/simonw/datasette/issues/1590#issuecomment-1012653966,https://api.github.com/repos/simonw/datasette/issues/1590,1012653966,IC_kwDOBm6k_c48W9-O,9599,2022-01-14T00:59:07Z,2022-01-14T00:59:07Z,OWNER,"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:
```python
application = URLRouter([
re_path(r""^datasettes/.*"", asgi_cors(datasette_.app(remove_path_prefix=""datasettes/""), allow_all=True)),
])
```","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1099723916,
https://github.com/simonw/datasette/issues/1590#issuecomment-1012583091,https://api.github.com/repos/simonw/datasette/issues/1590,1012583091,IC_kwDOBm6k_c48Wsqz,9599,2022-01-13T22:41:15Z,2022-01-13T22:41:15Z,OWNER,"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!","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1099723916,
https://github.com/simonw/datasette/issues/1590#issuecomment-1010540923,https://api.github.com/repos/simonw/datasette/issues/1590,1010540923,IC_kwDOBm6k_c48O6F7,9599,2022-01-12T01:33:49Z,2022-01-12T01:33:49Z,OWNER,"Looking closer at the code quoted above, it doesn't modify `path` or `raw_path` at all - ALL it does is add the `route_path` to the scope.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1099723916,
https://github.com/simonw/datasette/issues/1590#issuecomment-1010538188,https://api.github.com/repos/simonw/datasette/issues/1590,1010538188,IC_kwDOBm6k_c48O5bM,9599,2022-01-12T01:28:41Z,2022-01-12T01:30:43Z,OWNER,"Oh wait! It looks like `route_path` is something I invented there.
Yup, I added it in https://github.com/simonw/datasette/commit/a63412152518581c6a3d4e142b937e27dabdbfdb - commit message says:
> - new `route_path` key in `request.scope` storing the path that was used for routing with the `base_url` prefix stripped
So actually part of the mystery here is: why does the Fly hosted one NOT have that key?","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1099723916,
https://github.com/simonw/datasette/issues/1590#issuecomment-1010538016,https://api.github.com/repos/simonw/datasette/issues/1590,1010538016,IC_kwDOBm6k_c48O5Yg,9599,2022-01-12T01:28:19Z,2022-01-12T01:28:19Z,OWNER,"The Daphne one has this key: `'route_path': '/-/asgi-scope',`
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: https://github.com/simonw/datasette/blob/8c401ee0f054de2f568c3a8302c9223555146407/datasette/app.py#L1143-L1149","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1099723916,
https://github.com/simonw/datasette/issues/1590#issuecomment-1010537058,https://api.github.com/repos/simonw/datasette/issues/1590,1010537058,IC_kwDOBm6k_c48O5Ji,9599,2022-01-12T01:26:34Z,2022-01-12T01:26:34Z,OWNER,"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
```
{'actor': None,
'asgi': {'version': '3.0'},
'client': ['127.0.0.1', 53767],
'csrftoken': ._asgi_csrf_decorator..app_wrapped_with_csrf..get_csrftoken at 0x1122aeef0>,
'headers': [(b'host', b'127.0.0.1:8032'),
(b'user-agent',
b'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko'
b'/20100101 Firefox/95.0'),
(b'accept',
b'text/html,application/xhtml+xml,application/xml;q=0.9,image/'
b'avif,image/webp,*/*;q=0.8'),
(b'accept-language', b'en-US,en;q=0.5'),
(b'accept-encoding', b'gzip, deflate'),
(b'dnt', b'1'),
(b'connection', b'keep-alive'),
(b'cookie', b'_ga=GA1.1.742283954.1628542653'),
(b'upgrade-insecure-requests', b'1'),
(b'sec-fetch-dest', b'document'),
(b'sec-fetch-mode', b'navigate'),
(b'sec-fetch-site', b'none'),
(b'sec-fetch-user', b'?1')],
'http_version': '1.1',
'method': 'GET',
'path': '/datasettes/-/asgi-scope',
'path_remaining': '',
'query_string': b'',
'raw_path': b'/datasettes/-/asgi-scope',
'root_path': '',
'route_path': '/-/asgi-scope',
'scheme': 'http',
'server': ['127.0.0.1', 8032],
'type': 'http',
'url_route': {'kwargs': {}}}
```
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
```
{'actor': None,
'asgi': {'spec_version': '2.1', 'version': '3.0'},
'client': ('86.109.12.167', 0),
'csrftoken': ._asgi_csrf_decorator..app_wrapped_with_csrf..get_csrftoken at 0x7f4c0413bca0>,
'headers': [(b'host', b'datasette-apache-proxy-demo.fly.dev'),
(b'user-agent',
b'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko'
b'/20100101 Firefox/95.0'),
(b'accept',
b'text/html,application/xhtml+xml,application/xml;q=0.9,image/'
b'avif,image/webp,*/*;q=0.8'),
(b'accept-language', b'en-US,en;q=0.5'),
(b'accept-encoding', b'gzip, deflate, br'),
(b'dnt', b'1'),
(b'x-request-start', b't=1641950740651658'),
(b'sec-fetch-dest', b'document'),
(b'sec-fetch-mode', b'navigate'),
(b'sec-fetch-site', b'none'),
(b'sec-fetch-user', b'?1'),
(b'fly-client-ip', b'24.5.172.176'),
(b'x-forwarded-for',
b'24.5.172.176, 213.188.193.173, 86.109.12.167'),
(b'fly-forwarded-proto', b'https'),
(b'x-forwarded-proto', b'https'),
(b'fly-forwarded-ssl', b'on'),
(b'x-forwarded-ssl', b'on'),
(b'fly-forwarded-port', b'443'),
(b'x-forwarded-port', b'443'),
(b'fly-region', b'sjc'),
(b'fly-request-id', b'01FS5Y805BX43HM94T8XW610KG'),
(b'via', b'2 fly.io'),
(b'fly-dispatch-start', b't=1641950740683198;instance=87f188a2'),
(b'x-forwarded-host', b'datasette-apache-proxy-demo.fly.dev'),
(b'x-forwarded-server', b'localhost'),
(b'connection', b'Keep-Alive')],
'http_version': '1.1',
'method': 'GET',
'path': '/-/asgi-scope',
'query_string': b'',
'raw_path': b'/-/asgi-scope',
'root_path': '',
'scheme': 'https',
'server': ('127.0.0.1', 8001),
'type': 'http',
'url_route': {'kwargs': {}}}
```
The version that works as ` 'raw_path': b'/-/asgi-scope'` - the version that fails has `'raw_path': b'/datasettes/-/asgi-scope'`.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1099723916,
https://github.com/simonw/datasette/issues/1590#issuecomment-1010533133,https://api.github.com/repos/simonw/datasette/issues/1590,1010533133,IC_kwDOBm6k_c48O4MN,9599,2022-01-12T01:19:19Z,2022-01-12T01:19:19Z,OWNER,"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!","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1099723916,