Files
Nominatim/nominatim/server/starlette/server.py
Sarah Hoffmann 8f4426fbc8 reorganize code around result formatting
Code is now organized by api version. So formatting has moved to
the api.v1 module. Instead of holding a separate ResultFormatter
object per result format, simply move the functions to the
formater collector and hand in the requested format as a parameter.
Thus reorganized, the api.v1 module can export three simple functions
for result formatting which in turn makes the code that uses
the formatters much simpler.
2023-01-24 17:20:51 +01:00

75 lines
2.3 KiB
Python

# SPDX-License-Identifier: GPL-2.0-only
#
# This file is part of Nominatim. (https://nominatim.org)
#
# Copyright (C) 2023 by the Nominatim developer community.
# For a full list of authors see the git log.
"""
Server implementation using the starlette webserver framework.
"""
from typing import Any, Type, Optional, Mapping
from pathlib import Path
from starlette.applications import Starlette
from starlette.routing import Route
from starlette.exceptions import HTTPException
from starlette.responses import Response
from starlette.requests import Request
from nominatim.api import NominatimAPIAsync, StatusResult
import nominatim.api.v1 as api_impl
CONTENT_TYPE = {
'text': 'text/plain; charset=utf-8',
'xml': 'text/xml; charset=utf-8'
}
def parse_format(request: Request, rtype: Type[Any], default: str) -> None:
""" Get and check the 'format' parameter and prepare the formatter.
`rtype` describes the expected return type and `default` the
format value to assume when no parameter is present.
"""
fmt = request.query_params.get('format', default=default)
if not api_impl.supports_format(rtype, fmt):
raise HTTPException(400, detail="Parameter 'format' must be one of: " +
', '.join(api_impl.list_formats(rtype)))
request.state.format = fmt
def format_response(request: Request, result: Any) -> Response:
""" Render response into a string according.
"""
fmt = request.state.format
return Response(api_impl.format_result(result, fmt),
media_type=CONTENT_TYPE.get(fmt, 'application/json'))
async def on_status(request: Request) -> Response:
""" Implementation of status endpoint.
"""
parse_format(request, StatusResult, 'text')
result = await request.app.state.API.status()
response = format_response(request, result)
if request.state.format == 'text' and result.status:
response.status_code = 500
return response
V1_ROUTES = [
Route('/status', endpoint=on_status)
]
def get_application(project_dir: Path,
environ: Optional[Mapping[str, str]] = None) -> Starlette:
""" Create a Nominatim falcon ASGI application.
"""
app = Starlette(debug=True, routes=V1_ROUTES)
app.state.API = NominatimAPIAsync(project_dir, environ)
return app