diff --git a/datasette/views/base.py b/datasette/views/base.py index 6cd93531..9a41db56 100644 --- a/datasette/views/base.py +++ b/datasette/views/base.py @@ -73,13 +73,20 @@ class BaseView: request.path.endswith(".json") or request.headers.get("content-type") == "application/json" ): - return Response.json( + response = Response.json( {"ok": False, "error": "Method not allowed"}, status=405 ) - return Response.text("Method not allowed", status=405) + else: + response = Response.text("Method not allowed", status=405) + if self.ds.cors: + add_cors_headers(response.headers) + return response async def options(self, request, *args, **kwargs): - return await self.method_not_allowed(request) + r = Response.text("ok") + if self.ds.cors: + add_cors_headers(r.headers) + return r async def get(self, request, *args, **kwargs): return await self.method_not_allowed(request) @@ -155,12 +162,6 @@ class BaseView: class DataView(BaseView): name = "" - async def options(self, request, *args, **kwargs): - r = Response.text("ok") - if self.ds.cors: - add_cors_headers(r.headers) - return r - def redirect(self, request, path, forward_querystring=True, remove_args=None): if request.query_string and "?" not in path and forward_querystring: path = f"{path}?{request.query_string}" diff --git a/tests/test_api.py b/tests/test_api.py index de0223e2..24549d42 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -897,14 +897,32 @@ def test_config_force_https_urls(): ("/fixtures/no_primary_key.json", 200), # A 400 invalid SQL query should still have the header: ("/fixtures.json?sql=select+blah", 400), + # Write APIs + ("/fixtures/-/create", 405), + ("/fixtures/facetable/-/insert", 405), + ("/fixtures/facetable/-/drop", 405), ], ) -def test_cors(app_client_with_cors, path, status_code): +def test_cors( + app_client_with_cors, + app_client_two_attached_databases_one_immutable, + path, + status_code, +): response = app_client_with_cors.get(path) assert response.status == status_code assert response.headers["Access-Control-Allow-Origin"] == "*" assert response.headers["Access-Control-Allow-Headers"] == "Authorization" assert response.headers["Access-Control-Expose-Headers"] == "Link" + # Same request to app_client_two_attached_databases_one_immutable + # should not have those headers - I'm using that fixture because + # regular app_client doesn't have immutable fixtures.db which means + # the test for /fixtures.db returns a 403 error + response = app_client_two_attached_databases_one_immutable.get(path) + assert response.status == status_code + assert "Access-Control-Allow-Origin" not in response.headers + assert "Access-Control-Allow-Headers" not in response.headers + assert "Access-Control-Expose-Headers" not in response.headers @pytest.mark.parametrize(