Add CORS headers in the API response, add a debug option to get verbose debugging from Bottle webserver
This commit is contained in:
parent
8a74a79ac2
commit
03d2ad6f7f
@ -233,4 +233,5 @@ def serve(config):
|
|||||||
# standard logging
|
# standard logging
|
||||||
server = web_app.QuietWSGIRefServer
|
server = web_app.QuietWSGIRefServer
|
||||||
|
|
||||||
app.run(host=config["host"], port=config["port"], server=server)
|
app.run(host=config["host"], port=config["port"], server=server,
|
||||||
|
debug=config["debug"])
|
||||||
|
@ -63,6 +63,8 @@ DEFAULT_CONFIG = {
|
|||||||
"search_index": None,
|
"search_index": None,
|
||||||
# Web app port
|
# Web app port
|
||||||
"port": 8080,
|
"port": 8080,
|
||||||
|
# Debug mode for webserver
|
||||||
|
"debug": False,
|
||||||
# Web app host to listen on
|
# Web app host to listen on
|
||||||
"host": "127.0.0.1",
|
"host": "127.0.0.1",
|
||||||
# Web server to use to serve the webapp (see Bottle deployment doc)
|
# Web server to use to serve the webapp (see Bottle deployment doc)
|
||||||
@ -126,6 +128,7 @@ def validate_config(config, check_with_data):
|
|||||||
|
|
||||||
assert config["database"] is None or isinstance(config["database"], str) # noqa: E501
|
assert config["database"] is None or isinstance(config["database"], str) # noqa: E501
|
||||||
|
|
||||||
|
assert isinstance(config["debug"], bool)
|
||||||
assert isinstance(config["port"], int)
|
assert isinstance(config["port"], int)
|
||||||
assert isinstance(config["host"], str)
|
assert isinstance(config["host"], str)
|
||||||
assert config["webserver"] is None or isinstance(config["webserver"], str) # noqa: E501
|
assert config["webserver"] is None or isinstance(config["webserver"], str) # noqa: E501
|
||||||
|
@ -42,7 +42,6 @@ def _serve_static_file(filename):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_app(config):
|
def get_app(config):
|
||||||
"""
|
"""
|
||||||
Get a Bottle app instance with all the routes set-up.
|
Get a Bottle app instance with all the routes set-up.
|
||||||
@ -51,7 +50,7 @@ def get_app(config):
|
|||||||
"""
|
"""
|
||||||
get_session = database.init_db(config["database"], config["search_index"])
|
get_session = database.init_db(config["database"], config["search_index"])
|
||||||
|
|
||||||
app = bottle.default_app()
|
app = bottle.Bottle()
|
||||||
app.install(DatabasePlugin(get_session))
|
app.install(DatabasePlugin(get_session))
|
||||||
app.install(ConfigPlugin(config))
|
app.install(ConfigPlugin(config))
|
||||||
app.config.setdefault("canister.log_level", logging.root.level)
|
app.config.setdefault("canister.log_level", logging.root.level)
|
||||||
@ -60,24 +59,40 @@ def get_app(config):
|
|||||||
app.install(canister.Canister())
|
app.install(canister.Canister())
|
||||||
# Use DateAwareJSONEncoder to dump JSON strings
|
# Use DateAwareJSONEncoder to dump JSON strings
|
||||||
# From http://stackoverflow.com/questions/21282040/bottle-framework-how-to-return-datetime-in-json-response#comment55718456_21282666. pylint: disable=locally-disabled,line-too-long
|
# From http://stackoverflow.com/questions/21282040/bottle-framework-how-to-return-datetime-in-json-response#comment55718456_21282666. pylint: disable=locally-disabled,line-too-long
|
||||||
bottle.install(
|
app.install(
|
||||||
bottle.JSONPlugin(
|
bottle.JSONPlugin(
|
||||||
json_dumps=functools.partial(json.dumps, cls=DateAwareJSONEncoder)
|
json_dumps=functools.partial(json.dumps, cls=DateAwareJSONEncoder)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# API v1 routes
|
# Enable CORS
|
||||||
app.route("/api/v1/", "GET", api_routes.index_v1)
|
@app.hook('after_request')
|
||||||
|
def enable_cors():
|
||||||
|
"""
|
||||||
|
Add CORS headers at each request.
|
||||||
|
"""
|
||||||
|
# The str() call is required as we import unicode_literal and WSGI
|
||||||
|
# headers list should have plain str type.
|
||||||
|
bottle.response.headers[str('Access-Control-Allow-Origin')] = '*'
|
||||||
|
bottle.response.headers[str('Access-Control-Allow-Methods')] = (
|
||||||
|
'PUT, GET, POST, DELETE, OPTIONS'
|
||||||
|
)
|
||||||
|
bottle.response.headers[str('Access-Control-Allow-Headers')] = (
|
||||||
|
'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'
|
||||||
|
)
|
||||||
|
|
||||||
app.route("/api/v1/time_to_places", "GET",
|
# API v1 routes
|
||||||
|
app.route("/api/v1/", ["GET", "OPTIONS"], api_routes.index_v1)
|
||||||
|
|
||||||
|
app.route("/api/v1/time_to_places", ["GET", "OPTIONS"],
|
||||||
api_routes.time_to_places_v1)
|
api_routes.time_to_places_v1)
|
||||||
|
|
||||||
app.route("/api/v1/flats", "GET", api_routes.flats_v1)
|
app.route("/api/v1/flats", ["GET", "OPTIONS"], api_routes.flats_v1)
|
||||||
app.route("/api/v1/flats/:flat_id", "GET", api_routes.flat_v1)
|
app.route("/api/v1/flats/:flat_id", ["GET", "OPTIONS"], api_routes.flat_v1)
|
||||||
app.route("/api/v1/flats/:flat_id", "PATCH",
|
app.route("/api/v1/flats/:flat_id", ["PATCH", "OPTIONS"],
|
||||||
api_routes.update_flat_v1)
|
api_routes.update_flat_v1)
|
||||||
|
|
||||||
app.route("/api/v1/ics/visits.ics", "GET",
|
app.route("/api/v1/ics/visits.ics", ["GET", "OPTIONS"],
|
||||||
api_routes.ics_feed_v1)
|
api_routes.ics_feed_v1)
|
||||||
|
|
||||||
app.route("/api/v1/search", "POST", api_routes.search_v1)
|
app.route("/api/v1/search", "POST", api_routes.search_v1)
|
||||||
|
@ -103,6 +103,10 @@ def flats_v1(config, db):
|
|||||||
|
|
||||||
:return: The available flats objects in a JSON ``data`` dict.
|
:return: The available flats objects in a JSON ``data`` dict.
|
||||||
"""
|
"""
|
||||||
|
if bottle.request.method == 'OPTIONS':
|
||||||
|
# CORS
|
||||||
|
return ''
|
||||||
|
|
||||||
try:
|
try:
|
||||||
db_query = db.query(flat_model.Flat)
|
db_query = db.query(flat_model.Flat)
|
||||||
|
|
||||||
@ -139,6 +143,10 @@ def flat_v1(flat_id, config, db):
|
|||||||
|
|
||||||
:return: The flat object in a JSON ``data`` dict.
|
:return: The flat object in a JSON ``data`` dict.
|
||||||
"""
|
"""
|
||||||
|
if bottle.request.method == 'OPTIONS':
|
||||||
|
# CORS
|
||||||
|
return {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
flat = db.query(flat_model.Flat).filter_by(id=flat_id).first()
|
flat = db.query(flat_model.Flat).filter_by(id=flat_id).first()
|
||||||
|
|
||||||
@ -171,6 +179,10 @@ def update_flat_v1(flat_id, config, db):
|
|||||||
|
|
||||||
:return: The new flat object in a JSON ``data`` dict.
|
:return: The new flat object in a JSON ``data`` dict.
|
||||||
"""
|
"""
|
||||||
|
if bottle.request.method == 'OPTIONS':
|
||||||
|
# CORS
|
||||||
|
return {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
flat = db.query(flat_model.Flat).filter_by(id=flat_id).first()
|
flat = db.query(flat_model.Flat).filter_by(id=flat_id).first()
|
||||||
if not flat:
|
if not flat:
|
||||||
@ -204,6 +216,10 @@ def time_to_places_v1(config):
|
|||||||
:return: The JSON dump of the places to compute time to (dict of places
|
:return: The JSON dump of the places to compute time to (dict of places
|
||||||
names mapped to GPS coordinates).
|
names mapped to GPS coordinates).
|
||||||
"""
|
"""
|
||||||
|
if bottle.request.method == 'OPTIONS':
|
||||||
|
# CORS
|
||||||
|
return {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
places = {}
|
places = {}
|
||||||
for constraint_name, constraint in config["constraints"].items():
|
for constraint_name, constraint in config["constraints"].items():
|
||||||
@ -231,6 +247,10 @@ def search_v1(db, config):
|
|||||||
|
|
||||||
:return: The matching flat objects in a JSON ``data`` dict.
|
:return: The matching flat objects in a JSON ``data`` dict.
|
||||||
"""
|
"""
|
||||||
|
if bottle.request.method == 'OPTIONS':
|
||||||
|
# CORS
|
||||||
|
return {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
query = json.load(bottle.request.body)["query"]
|
query = json.load(bottle.request.body)["query"]
|
||||||
@ -260,6 +280,10 @@ def ics_feed_v1(config, db):
|
|||||||
|
|
||||||
:return: The ICS feed for the visits.
|
:return: The ICS feed for the visits.
|
||||||
"""
|
"""
|
||||||
|
if bottle.request.method == 'OPTIONS':
|
||||||
|
# CORS
|
||||||
|
return {}
|
||||||
|
|
||||||
cal = vobject.iCalendar()
|
cal = vobject.iCalendar()
|
||||||
try:
|
try:
|
||||||
flats_with_visits = db.query(flat_model.Flat).filter(
|
flats_with_visits = db.query(flat_model.Flat).filter(
|
||||||
|
Loading…
Reference in New Issue
Block a user