diff --git a/swh/web/api/views/origin.py b/swh/web/api/views/origin.py --- a/swh/web/api/views/origin.py +++ b/swh/web/api/views/origin.py @@ -6,6 +6,7 @@ from distutils.util import strtobool from functools import partial +from swh.search.exc import SearchQuerySyntaxError from swh.web.api.apidoc import api_doc, format_docstring from swh.web.api.apiurls import api_route from swh.web.api.utils import ( @@ -194,17 +195,20 @@ with_visit = request.query_params.get("with_visit", "false") visit_type = request.query_params.get("visit_type") - (results, page_token) = api_lookup( - archive.search_origin, - url_pattern, - bool(strtobool(use_ql)), - limit, - bool(strtobool(with_visit)), - [visit_type] if visit_type else None, - page_token, - enrich_fn=enrich_origin_search_result, - request=request, - ) + try: + (results, page_token) = api_lookup( + archive.search_origin, + url_pattern, + bool(strtobool(use_ql)), + limit, + bool(strtobool(with_visit)), + [visit_type] if visit_type else None, + page_token, + enrich_fn=enrich_origin_search_result, + request=request, + ) + except SearchQuerySyntaxError as e: + raise BadInputExc(f"Syntax error in search query: {e.args[0]}") if page_token is not None: query_params = {k: v for (k, v) in request.GET.dict().items()} diff --git a/swh/web/tests/api/views/test_origin.py b/swh/web/tests/api/views/test_origin.py --- a/swh/web/tests/api/views/test_origin.py +++ b/swh/web/tests/api/views/test_origin.py @@ -12,6 +12,7 @@ from swh.indexer.storage.model import OriginIntrinsicMetadataRow from swh.model.hashutil import hash_to_bytes from swh.model.model import Origin, OriginVisit, OriginVisitStatus +from swh.search.exc import SearchQuerySyntaxError from swh.search.interface import PagedResult from swh.storage.exc import StorageAPIError, StorageDBError from swh.storage.utils import now @@ -557,7 +558,7 @@ results=ORIGINS, next_page_token=None, ) - query = "origin = 'github.com'" + query = "origin : 'github.com'" url = reverse( "api-1-origin-search", @@ -572,6 +573,30 @@ ) +def test_api_origin_search_ql_syntax_error(api_client, mocker): + mock_archive_search = mocker.patch("swh.web.common.archive.search") + mock_archive_search.origin_search.side_effect = SearchQuerySyntaxError( + "Invalid syntax" + ) + + query = "this is not a valid query" + + url = reverse( + "api-1-origin-search", + url_args={"url_pattern": query}, + query_params={"visit_type": "git", "use_ql": "true"}, + ) + rv = check_api_get_responses(api_client, url, status_code=400) + assert rv.data == { + "exception": "BadInputExc", + "reason": "Syntax error in search query: Invalid syntax", + } + + mock_archive_search.origin_search.assert_called_with( + query=query, page_token=None, with_visit=False, visit_types=["git"], limit=70 + ) + + @pytest.mark.parametrize("backend", ["swh-search", "swh-storage"]) @pytest.mark.parametrize("limit", [1, 2, 3, 10]) def test_api_origin_search_scroll(api_client, archive_data, mocker, limit, backend):