add support for starlette framework

This commit is contained in:
Sarah Hoffmann
2022-12-05 11:32:57 +01:00
parent 8aa01c9c8e
commit 1adb0a9886
3 changed files with 73 additions and 5 deletions

View File

@@ -202,7 +202,7 @@ class AdminServe:
for testing and development. Do not use it in production setups!
There are different webservers available. The default 'php' engine
runs the classic PHP frontend. 'sanic' and 'falcon' are Python servers
runs the classic PHP frontend. The other engines are Python servers
which run the new Python frontend code. This is highly experimental
at the moment and may not include the full API.
@@ -214,7 +214,7 @@ class AdminServe:
group.add_argument('--server', default='127.0.0.1:8088',
help='The address the server will listen to.')
group.add_argument('--engine', default='php',
choices=('php', 'sanic', 'falcon'),
choices=('php', 'sanic', 'falcon', 'starlette'),
help='Webserver framework to run. (default: php)')
@@ -236,11 +236,15 @@ class AdminServe:
app = nominatim.server.sanic.server.get_application(args.project_dir)
app.run(host=host, port=port, debug=True)
elif args.engine == 'falcon':
else:
import uvicorn
import nominatim.server.falcon.server
app = nominatim.server.falcon.server.get_application(args.project_dir)
if args.engine == 'falcon':
import nominatim.server.falcon.server as server_module
elif args.engine == 'starlette':
import nominatim.server.starlette.server as server_module
app = server_module.get_application(args.project_dir)
uvicorn.run(app, host=host, port=port)
return 0

View File

View File

@@ -0,0 +1,64 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# This file is part of Nominatim. (https://nominatim.org)
#
# Copyright (C) 2022 by the Nominatim developer community.
# For a full list of authors see the git log.
"""
Server implementation using the starlette webserver framework.
"""
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 nominatim.api import NominatimAPIAsync
from nominatim.apicmd.status import StatusResult
import nominatim.result_formatter.v1 as formatting
CONTENT_TYPE = {
'text': 'text/plain; charset=utf-8',
'xml': 'text/xml; charset=utf-8'
}
FORMATTERS = {
StatusResult: formatting.create(StatusResult)
}
def parse_format(request, rtype, default):
fmt = request.query_params.get('format', default=default)
fmtter = FORMATTERS[rtype]
if not fmtter.supports_format(fmt):
raise HTTPException(400, detail="Parameter 'format' must be one of: " +
', '.join(fmtter.list_formats()))
request.state.format = fmt
request.state.formatter = fmtter
def format_response(request, result):
fmt = request.state.format
return Response(request.state.formatter.format(result, fmt),
media_type=CONTENT_TYPE.get(fmt, 'application/json'))
async def on_status(request):
parse_format(request, StatusResult, 'text')
result = await request.app.state.API.status()
return format_response(request, result)
V1_ROUTES = [
Route('/status', endpoint=on_status)
]
def get_application(project_dir: Path) -> Starlette:
app = Starlette(debug=True, routes=V1_ROUTES)
app.state.API = NominatimAPIAsync(project_dir)
return app