mirror of
https://github.com/YunoHost/moulinette.git
synced 2024-09-03 20:06:31 +02:00
api: Add a proper mechanism to allow specific, configurable CORS origins
This commit is contained in:
parent
4104704a87
commit
328107c946
2 changed files with 23 additions and 7 deletions
|
@ -53,7 +53,7 @@ class Moulinette:
|
|||
|
||||
|
||||
# Easy access to interfaces
|
||||
def api(host="localhost", port=80, routes={}, actionsmap=None, locales_dir=None):
|
||||
def api(host="localhost", port=80, routes={}, actionsmap=None, locales_dir=None, allowed_cors_origins=[]):
|
||||
"""Web server (API) interface
|
||||
|
||||
Run a HTTP server with the moulinette for an API usage.
|
||||
|
@ -73,6 +73,7 @@ def api(host="localhost", port=80, routes={}, actionsmap=None, locales_dir=None)
|
|||
Api(
|
||||
routes=routes,
|
||||
actionsmap=actionsmap,
|
||||
allowed_cors_origins=allowed_cors_origins,
|
||||
).run(host, port)
|
||||
except MoulinetteError as e:
|
||||
import logging
|
||||
|
|
|
@ -717,9 +717,11 @@ class Interface:
|
|||
|
||||
type = "api"
|
||||
|
||||
def __init__(self, routes={}, actionsmap=None):
|
||||
def __init__(self, routes={}, actionsmap=None, allowed_cors_origins=[]):
|
||||
actionsmap = ActionsMap(actionsmap, ActionsMapParser())
|
||||
|
||||
self.allowed_cors_origins = allowed_cors_origins
|
||||
|
||||
# Attempt to retrieve log queues from an APIQueueHandler
|
||||
handler = log.getHandlersByClass(APIQueueHandler, limit=1)
|
||||
if handler:
|
||||
|
@ -729,11 +731,18 @@ class Interface:
|
|||
# TODO: Return OK to 'OPTIONS' xhr requests (l173)
|
||||
app = Bottle(autojson=True)
|
||||
|
||||
# Wrapper which sets proper header
|
||||
def apiheader(callback):
|
||||
def cors(callback):
|
||||
def wrapper(*args, **kwargs):
|
||||
response.set_header("Access-Control-Allow-Origin", "*")
|
||||
return callback(*args, **kwargs)
|
||||
r = callback(*args, **kwargs)
|
||||
origin = request.headers.environ.get("HTTP_ORIGIN", "")
|
||||
if origin and origin in self.allowed_cors_origins:
|
||||
resp = r if isinstance(r, HTTPResponse) else response
|
||||
resp.headers['Access-Control-Allow-Origin'] = origin
|
||||
resp.headers['Access-Control-Allow-Methods'] = 'GET, HEAD, POST, PUT, OPTIONS, DELETE'
|
||||
resp.headers['Access-Control-Allow-Headers'] = 'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'
|
||||
resp.headers['Access-Control-Allow-Credentials'] = 'true'
|
||||
|
||||
return r
|
||||
|
||||
return wrapper
|
||||
|
||||
|
@ -751,7 +760,7 @@ class Interface:
|
|||
|
||||
# Install plugins
|
||||
app.install(filter_csrf)
|
||||
app.install(apiheader)
|
||||
app.install(cors)
|
||||
app.install(api18n)
|
||||
actionsmapplugin = _ActionsMapPlugin(actionsmap, log_queues)
|
||||
app.install(actionsmapplugin)
|
||||
|
@ -760,6 +769,12 @@ class Interface:
|
|||
self.display = actionsmapplugin.display
|
||||
self.prompt = actionsmapplugin.prompt
|
||||
|
||||
def handle_options():
|
||||
return HTTPResponse("", 204)
|
||||
|
||||
app.route('/<:re:.*>', method="OPTIONS",
|
||||
callback=handle_options, skip=["actionsmap"])
|
||||
|
||||
# Append additional routes
|
||||
# TODO: Add optional authentication to those routes?
|
||||
for (m, p), c in routes.items():
|
||||
|
|
Loading…
Reference in a new issue