From e490a30a4a926a55543fe3222e808233069b869e Mon Sep 17 00:00:00 2001 From: Sarah Hoffmann Date: Tue, 24 Jan 2023 21:26:32 +0100 Subject: [PATCH] add support for CORS headers Adds the additional dependency to sanic-cors for the Sanic server. --- .github/workflows/ci-tests.yml | 2 +- .mypy.ini | 3 +++ docs/admin/Installation.md | 2 +- nominatim/cli.py | 2 +- nominatim/server/falcon/server.py | 2 +- nominatim/server/sanic/server.py | 4 ++++ nominatim/server/starlette/server.py | 11 ++++++++++- 7 files changed, 21 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 0f4aea26..a4de7149 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -107,7 +107,7 @@ jobs: if: matrix.flavour == 'oldstuff' - name: Install Python webservers - run: pip3 install falcon sanic sanic-testing starlette + run: pip3 install falcon sanic sanic-testing sanic-cors starlette - name: Install latest pylint/mypy run: pip3 install -U pylint mypy types-PyYAML types-jinja2 types-psycopg2 types-psutil types-requests typing-extensions asgi_lifespan sqlalchemy2-stubs diff --git a/.mypy.ini b/.mypy.ini index ef2057d4..611c3c5d 100644 --- a/.mypy.ini +++ b/.mypy.ini @@ -1,6 +1,9 @@ [mypy] plugins = sqlalchemy.ext.mypy.plugin +[mypy-sanic_cors.*] +ignore_missing_imports = True + [mypy-icu.*] ignore_missing_imports = True diff --git a/docs/admin/Installation.md b/docs/admin/Installation.md index f6692f58..663d5c37 100644 --- a/docs/admin/Installation.md +++ b/docs/admin/Installation.md @@ -66,7 +66,7 @@ For running the experimental Python frontend: * one of the following web frameworks: * [falcon](https://falconframework.org/) (3.0+) - * [sanic](https://sanic.dev) + * [sanic](https://sanic.dev) and (optionally) [sanic-cors](https://github.com/ashleysommer/sanic-cors) * [starlette](https://www.starlette.io/) * [uvicorn](https://www.uvicorn.org/) (only with falcon and starlette framworks) diff --git a/nominatim/cli.py b/nominatim/cli.py index cedbdb4a..d34ef118 100644 --- a/nominatim/cli.py +++ b/nominatim/cli.py @@ -236,7 +236,7 @@ class AdminServe: server_module = importlib.import_module('nominatim.server.sanic.server') app = server_module.get_application(args.project_dir) - app.run(host=host, port=port, debug=True) + app.run(host=host, port=port, debug=True, single_process=True) else: import uvicorn # pylint: disable=import-outside-toplevel diff --git a/nominatim/server/falcon/server.py b/nominatim/server/falcon/server.py index ddbd2ca6..4295b3f3 100644 --- a/nominatim/server/falcon/server.py +++ b/nominatim/server/falcon/server.py @@ -65,7 +65,7 @@ def get_application(project_dir: Path, """ api = NominatimAPIAsync(project_dir, environ) - app = App() + app = App(cors_enable=api.config.get_bool('CORS_NOACCESSCONTROL')) for name, func in api_impl.ROUTES: app.add_route('/' + name, EndpointWrapper(func, api)) diff --git a/nominatim/server/sanic/server.py b/nominatim/server/sanic/server.py index 57b374d0..98e6b6e2 100644 --- a/nominatim/server/sanic/server.py +++ b/nominatim/server/sanic/server.py @@ -58,6 +58,10 @@ def get_application(project_dir: Path, app.ctx.api = NominatimAPIAsync(project_dir, environ) + if app.ctx.api.config.get_bool('CORS_NOACCESSCONTROL'): + from sanic_cors import CORS # pylint: disable=import-outside-toplevel + CORS(app) + for name, func in api_impl.ROUTES: app.add_route(_wrap_endpoint(func), f"/{name}", name=f"v1_{name}_simple") diff --git a/nominatim/server/starlette/server.py b/nominatim/server/starlette/server.py index 2bf569ed..dfbdc502 100644 --- a/nominatim/server/starlette/server.py +++ b/nominatim/server/starlette/server.py @@ -15,7 +15,10 @@ from starlette.routing import Route from starlette.exceptions import HTTPException from starlette.responses import Response from starlette.requests import Request +from starlette.middleware import Middleware +from starlette.middleware.cors import CORSMiddleware +from nominatim.config import Configuration from nominatim.api import NominatimAPIAsync import nominatim.api.v1 as api_impl @@ -55,11 +58,17 @@ def get_application(project_dir: Path, environ: Optional[Mapping[str, str]] = None) -> Starlette: """ Create a Nominatim falcon ASGI application. """ + config = Configuration(project_dir, environ) + routes = [] for name, func in api_impl.ROUTES: routes.append(Route(f"/{name}", endpoint=_wrap_endpoint(func))) - app = Starlette(debug=True, routes=routes) + middleware = [] + if config.get_bool('CORS_NOACCESSCONTROL'): + middleware.append(Middleware(CORSMiddleware, allow_origins=['*'])) + + app = Starlette(debug=True, routes=routes, middleware=middleware) app.state.API = NominatimAPIAsync(project_dir, environ) -- 2.39.5