From d9f9ed50276fca2154f1c966a39d7cd25666ff43 Mon Sep 17 00:00:00 2001 From: pengboyu-dev <203494526+pengboyu-dev@users.noreply.github.com> Date: Fri, 25 Sep 2026 02:34:45 +0800 Subject: [PATCH] Don't 500 on ?_facets=x Tighten up code that extracts `?_facet=` or `?_facet_type=` parameters. --- datasette/facets.py | 2 +- tests/test_facets.py | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/datasette/facets.py b/datasette/facets.py index 394eafad..69ac2c42 100644 --- a/datasette/facets.py +++ b/datasette/facets.py @@ -39,7 +39,7 @@ def load_facet_configs(request, table_config): ) qs_pairs = urllib.parse.parse_qs(request.query_string, keep_blank_values=True) for key, values in qs_pairs.items(): - if key.startswith("_facet"): + if key == "_facet" or key.startswith("_facet_"): # Figure out the facet type if key == "_facet": type = "column" diff --git a/tests/test_facets.py b/tests/test_facets.py index eccfbb93..10325f9a 100644 --- a/tests/test_facets.py +++ b/tests/test_facets.py @@ -5,13 +5,47 @@ import pytest from datasette.app import Datasette from datasette.database import Database -from datasette.facets import ArrayFacet, ColumnFacet, DateFacet, Facet +from datasette.facets import ( + ArrayFacet, + ColumnFacet, + DateFacet, + Facet, + load_facet_configs, +) from datasette.utils import detect_json1 from datasette.utils.asgi import Request from .fixtures import make_app_client +@pytest.mark.parametrize( + "query_string", + ("_facets=ignored", "_facet=state&_facets=ignored", "_facets=ignored&_facet=state"), +) +@pytest.mark.parametrize("table_config", ({}, {"facets": ["state"]})) +def test_facet_configs_ignore_unrelated_prefixes(query_string, table_config): + expected = load_facet_configs( + Request.fake("/?_facet=state" if "_facet=" in query_string else "/"), + table_config, + ) + assert ( + load_facet_configs(Request.fake("/?" + query_string), table_config) == expected + ) + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "query_string", + ("_facet=state&_facets=ignored", "_facets=ignored&_facet=state"), +) +async def test_facet_ignores_unrelated_prefixes(ds_client, query_string): + response = await ds_client.get("/fixtures/facetable.json?" + query_string) + assert response.status_code == 200 + facets = response.json()["facet_results"]["results"] + assert set(facets) == {"state"} + assert facets["state"]["results"] + + @pytest.mark.asyncio async def test_column_facet_suggest(ds_client): facet = ColumnFacet(