From b3156107d7cae0e329b66dca8e400af434839a2c Mon Sep 17 00:00:00 2001 From: Andrew Grechkin Date: Fri, 6 Dec 2024 17:13:26 +0100 Subject: [PATCH] fix: support static files with spaces in their names Browser encodes all non-ASCII characters in URL into percent encoding format. Static files are served from the filesystem, and can have unsafe characters in their names. To support such files the request `path` should be decoded. --- datasette/utils/asgi.py | 4 ++-- tests/test_html.py | 8 ++++++++ tests/test_templates/pages/nested/filename with spaces | 0 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 tests/test_templates/pages/nested/filename with spaces diff --git a/datasette/utils/asgi.py b/datasette/utils/asgi.py index 1699847e16..3d52058b4c 100644 --- a/datasette/utils/asgi.py +++ b/datasette/utils/asgi.py @@ -2,7 +2,7 @@ import json from datasette.utils import MultiParams, calculate_etag from mimetypes import guess_type -from urllib.parse import parse_qs, urlunparse, parse_qsl +from urllib.parse import parse_qs, urlunparse, parse_qsl, unquote from pathlib import Path from http.cookies import SimpleCookie, Morsel import aiofiles @@ -318,7 +318,7 @@ async def inner_static(request, send): path = request.scope["url_route"]["kwargs"]["path"] headers = static_headers.copy() try: - full_path = (root_path / path).resolve().absolute() + full_path = (root_path / unquote(path)).resolve().absolute() except FileNotFoundError: await asgi_send_html(send, "404: Directory not found", 404) return diff --git a/tests/test_html.py b/tests/test_html.py index 4d95a8fa07..805797d656 100644 --- a/tests/test_html.py +++ b/tests/test_html.py @@ -116,6 +116,14 @@ def test_static_mounts(): ) as client: response = client.get("/custom-static/test_html.py") assert response.status_code == 200 + response = client.get( + "/custom-static/test_templates/pages/nested/filename with spaces" + ) + assert response.status_code == 200 + response = client.get( + "/custom-static/test_templates/pages/topic_{topic}/{slug}.html" + ) + assert response.status_code == 200 response = client.get("/custom-static/not_exists.py") assert response.status_code == 404 response = client.get("/custom-static/../LICENSE") diff --git a/tests/test_templates/pages/nested/filename with spaces b/tests/test_templates/pages/nested/filename with spaces new file mode 100644 index 0000000000..e69de29bb2