From b013aa1f7f133c93f7e2947d0224b4cd9fcd520a Mon Sep 17 00:00:00 2001 From: wheelman Date: Sun, 24 May 2026 09:51:13 +0530 Subject: [PATCH] Add CORS headers to /db?sql= query redirect (#2730) Closes #2728 --- datasette/views/database.py | 6 ++++-- tests/test_api.py | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/datasette/views/database.py b/datasette/views/database.py index faf870d0..0cf93832 100644 --- a/datasette/views/database.py +++ b/datasette/views/database.py @@ -61,8 +61,10 @@ class DatabaseView(View): if request.url_vars.get("format"): redirect_url += "." + request.url_vars.get("format") redirect_url += "?" + request.query_string - return Response.redirect(redirect_url) - return await QueryView()(request, datasette) + response = Response.redirect(redirect_url) + if datasette.cors: + add_cors_headers(response.headers) + return response if format_ not in ("html", "json"): raise NotFound("Invalid format: {}".format(format_)) diff --git a/tests/test_api.py b/tests/test_api.py index 392030d6..f6187529 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -717,6 +717,17 @@ def test_cors( assert "Access-Control-Max-Age" not in response.headers +def test_cors_query_redirect(app_client_with_cors): + # /db?sql= redirects to /db/-/query - the redirect itself needs CORS + # headers, otherwise browsers refuse to follow it cross-origin + response = app_client_with_cors.get( + "/fixtures?sql=select+1", follow_redirects=False + ) + assert response.status == 302 + assert response.headers["Location"] == "/fixtures/-/query?sql=select+1" + assert response.headers["Access-Control-Allow-Origin"] == "*" + + @pytest.mark.parametrize( "path", (