]> git.openstreetmap.org Git - nominatim.git/commitdiff
enable search endpoint only when search table is available
authorSarah Hoffmann <lonvia@denofr.de>
Wed, 13 Nov 2024 21:53:33 +0000 (22:53 +0100)
committerSarah Hoffmann <lonvia@denofr.de>
Thu, 14 Nov 2024 07:53:09 +0000 (08:53 +0100)
src/nominatim_api/server/falcon/server.py
src/nominatim_api/server/starlette/server.py
src/nominatim_api/v1/__init__.py
src/nominatim_api/v1/server_glue.py

index e252e3c8925f3c34daaabfa3d493df12d609357f..13e7931102677df26599dc02b2a53d820249f64d 100644 (file)
@@ -172,7 +172,7 @@ class APIMiddleware:
         assert self.app is not None
         legacy_urls = self.api.config.get_bool('SERVE_LEGACY_URLS')
         formatter = load_format_dispatcher('v1', self.api.config.project_dir)
         assert self.app is not None
         legacy_urls = self.api.config.get_bool('SERVE_LEGACY_URLS')
         formatter = load_format_dispatcher('v1', self.api.config.project_dir)
-        for name, func in api_impl.ROUTES:
+        for name, func in await api_impl.get_routes(self.api):
             endpoint = EndpointWrapper(name, func, self.api, formatter)
             self.app.add_route(f"/{name}", endpoint)
             if legacy_urls:
             endpoint = EndpointWrapper(name, func, self.api, formatter)
             self.app.add_route(f"/{name}", endpoint)
             if legacy_urls:
index 9d01492043d750ea2a204f96b2300f917c71923a..e6c97693dd8ab03f71bdbfa07129b83c044d7342 100644 (file)
@@ -7,7 +7,8 @@
 """
 Server implementation using the starlette webserver framework.
 """
 """
 Server implementation using the starlette webserver framework.
 """
-from typing import Any, Optional, Mapping, Callable, cast, Coroutine, Dict, Awaitable
+from typing import Any, Optional, Mapping, Callable, cast, Coroutine, Dict, \
+                   Awaitable, AsyncIterator
 from pathlib import Path
 import datetime as dt
 import asyncio
 from pathlib import Path
 import datetime as dt
 import asyncio
@@ -150,12 +151,12 @@ def get_application(project_dir: Path,
     }
 
     @contextlib.asynccontextmanager
     }
 
     @contextlib.asynccontextmanager
-    async def lifespan(app: Starlette) -> None:
+    async def lifespan(app: Starlette) -> AsyncIterator[Any]:
         app.state.API = NominatimAPIAsync(project_dir, environ)
         config = app.state.API.config
 
         legacy_urls = config.get_bool('SERVE_LEGACY_URLS')
         app.state.API = NominatimAPIAsync(project_dir, environ)
         config = app.state.API.config
 
         legacy_urls = config.get_bool('SERVE_LEGACY_URLS')
-        for name, func in api_impl.ROUTES:
+        for name, func in await api_impl.get_routes(app.state.API):
             endpoint = _wrap_endpoint(func)
             app.routes.append(Route(f"/{name}", endpoint=endpoint))
             if legacy_urls:
             endpoint = _wrap_endpoint(func)
             app.routes.append(Route(f"/{name}", endpoint=endpoint))
             if legacy_urls:
index f49de2a2968c3131f0f4388ea6e02c9e8ea3e07b..2304994f3bcdf52c12d84cccceab74e509467ebb 100644 (file)
@@ -8,4 +8,4 @@
 Implementation of API version v1 (aka the legacy version).
 """
 
 Implementation of API version v1 (aka the legacy version).
 """
 
-from .server_glue import ROUTES as ROUTES
+from .server_glue import get_routes as get_routes
index ee502d8b6382c62f1cea5dabd7fdcb21df874def..a6450bf25088fd85536cb7c9573daf4d672a7f61 100644 (file)
@@ -8,7 +8,7 @@
 Generic part of the server implementation of the v1 API.
 Combine with the scaffolding provided for the various Python ASGI frameworks.
 """
 Generic part of the server implementation of the v1 API.
 Combine with the scaffolding provided for the various Python ASGI frameworks.
 """
-from typing import Optional, Any, Type, Dict, cast
+from typing import Optional, Any, Type, Dict, cast, Sequence, Tuple
 from functools import reduce
 import dataclasses
 from urllib.parse import urlencode
 from functools import reduce
 import dataclasses
 from urllib.parse import urlencode
@@ -25,7 +25,8 @@ from ..results import DetailedResult, ReverseResults, SearchResult, SearchResult
 from ..localization import Locales
 from . import helpers
 from ..server import content_types as ct
 from ..localization import Locales
 from . import helpers
 from ..server import content_types as ct
-from ..server.asgi_adaptor import ASGIAdaptor
+from ..server.asgi_adaptor import ASGIAdaptor, EndpointFunc
+from ..sql.async_core_library import PGCORE_ERROR
 
 
 def build_response(adaptor: ASGIAdaptor, output: str, status: int = 200,
 
 
 def build_response(adaptor: ASGIAdaptor, output: str, status: int = 200,
@@ -417,12 +418,25 @@ async def polygons_endpoint(api: NominatimAPIAsync, params: ASGIAdaptor) -> Any:
     return build_response(params, params.formatting().format_result(results, fmt, {}))
 
 
     return build_response(params, params.formatting().format_result(results, fmt, {}))
 
 
-ROUTES = [
-    ('status', status_endpoint),
-    ('details', details_endpoint),
-    ('reverse', reverse_endpoint),
-    ('lookup', lookup_endpoint),
-    ('search', search_endpoint),
-    ('deletable', deletable_endpoint),
-    ('polygons', polygons_endpoint),
-]
+async def get_routes(api: NominatimAPIAsync) -> Sequence[Tuple[str, EndpointFunc]]:
+    routes = [
+        ('status', status_endpoint),
+        ('details', details_endpoint),
+        ('reverse', reverse_endpoint),
+        ('lookup', lookup_endpoint),
+        ('deletable', deletable_endpoint),
+        ('polygons', polygons_endpoint),
+    ]
+
+    def has_search_name(conn: sa.engine.Connection) -> bool:
+        insp = sa.inspect(conn)
+        return insp.has_table('search_name')
+
+    try:
+        async with api.begin() as conn:
+            if await conn.connection.run_sync(has_search_name):
+                routes.append(('search', search_endpoint))
+    except (PGCORE_ERROR, sa.exc.OperationalError):
+        pass  # ignored
+
+    return routes