2017-04-03 17:29:29 +02:00
# coding: utf-8
"""
This module contains the definition of the Bottle web app .
"""
2021-01-26 14:39:52 +01:00
from __future__ import absolute_import , division , print_function , unicode_literals
2017-04-03 17:29:29 +02:00
2017-04-13 23:24:31 +02:00
import functools
import json
2017-04-03 17:29:29 +02:00
import os
import bottle
2017-04-13 23:24:31 +02:00
import canister
2017-04-03 17:29:29 +02:00
from flatisfy import database
2017-04-13 23:24:31 +02:00
from flatisfy . tools import DateAwareJSONEncoder
2017-04-03 17:29:29 +02:00
from flatisfy . web . routes import api as api_routes
2017-04-13 23:24:31 +02:00
from flatisfy . web . configplugin import ConfigPlugin
2017-04-03 17:29:29 +02:00
from flatisfy . web . dbplugin import DatabasePlugin
2017-04-13 23:24:31 +02:00
class QuietWSGIRefServer ( bottle . WSGIRefServer ) :
"""
Quiet implementation of Bottle built - in WSGIRefServer , as ` Canister ` is
handling the logging through standard Python logging .
"""
2021-01-26 14:39:52 +01:00
2017-04-13 23:24:31 +02:00
# pylint: disable=locally-disabled,too-few-public-methods
quiet = True
2018-01-10 19:41:22 +01:00
def run ( self , app ) :
2021-01-26 16:49:43 +01:00
app . log . info ( " Server is now up and ready! Listening on %s : %s . " % ( self . host , self . port ) )
2018-01-10 19:41:22 +01:00
super ( QuietWSGIRefServer , self ) . run ( app )
2017-04-13 23:24:31 +02:00
2017-04-03 17:29:29 +02:00
def _serve_static_file ( filename ) :
"""
Helper function to serve static file .
"""
return bottle . static_file (
filename ,
2021-01-26 14:39:52 +01:00
root = os . path . join ( os . path . dirname ( os . path . realpath ( __file__ ) ) , " static " ) ,
2017-04-03 17:29:29 +02:00
)
2021-01-26 14:39:52 +01:00
2017-04-03 17:29:29 +02:00
def get_app ( config ) :
"""
Get a Bottle app instance with all the routes set - up .
: return : The built bottle app .
"""
2017-05-02 18:35:34 +02:00
get_session = database . init_db ( config [ " database " ] , config [ " search_index " ] )
2017-04-03 17:29:29 +02:00
2017-12-05 17:33:19 +01:00
app = bottle . Bottle ( )
2017-04-03 17:29:29 +02:00
app . install ( DatabasePlugin ( get_session ) )
2017-04-13 23:24:31 +02:00
app . install ( ConfigPlugin ( config ) )
2018-01-17 20:24:08 +01:00
app . config . setdefault ( " canister.log_level " , " DISABLED " )
2018-01-10 19:41:22 +01:00
app . config . setdefault ( " canister.log_path " , False )
2017-04-13 23:24:31 +02:00
app . config . setdefault ( " canister.debug " , False )
app . install ( canister . Canister ( ) )
# 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
2021-01-26 16:49:43 +01:00
app . install ( bottle . JSONPlugin ( json_dumps = functools . partial ( json . dumps , cls = DateAwareJSONEncoder ) ) )
2017-04-03 17:29:29 +02:00
2017-12-05 17:33:19 +01:00
# Enable CORS
2021-01-26 14:39:52 +01:00
@app.hook ( " after_request " )
2017-12-05 17:33:19 +01:00
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.
2021-01-26 14:39:52 +01:00
bottle . response . headers [ str ( " Access-Control-Allow-Origin " ) ] = str ( " * " )
2021-01-26 16:49:43 +01:00
bottle . response . headers [ str ( " Access-Control-Allow-Methods " ) ] = str ( " PUT, GET, POST, DELETE, OPTIONS, PATCH " )
2021-01-26 14:39:52 +01:00
bottle . response . headers [ str ( " Access-Control-Allow-Headers " ) ] = str (
" Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token "
2017-12-05 17:33:19 +01:00
)
2017-04-03 17:29:29 +02:00
# API v1 routes
2017-12-13 14:38:05 +01:00
app . route ( " /api/v1 " , [ " GET " , " OPTIONS " ] , api_routes . index_v1 )
2017-04-13 23:24:31 +02:00
2021-01-26 16:49:43 +01:00
app . route ( " /api/v1/time_to_places " , [ " GET " , " OPTIONS " ] , api_routes . time_to_places_v1 )
2017-04-13 23:24:31 +02:00
2017-12-05 17:33:19 +01:00
app . route ( " /api/v1/flats " , [ " GET " , " OPTIONS " ] , api_routes . flats_v1 )
app . route ( " /api/v1/flats/:flat_id " , [ " GET " , " OPTIONS " ] , api_routes . flat_v1 )
2021-01-26 14:39:52 +01:00
app . route ( " /api/v1/flats/:flat_id " , [ " PATCH " , " OPTIONS " ] , api_routes . update_flat_v1 )
2017-12-05 12:20:40 +01:00
2021-01-26 14:39:52 +01:00
app . route ( " /api/v1/ics/visits.ics " , [ " GET " , " OPTIONS " ] , api_routes . ics_feed_v1 )
2017-04-03 17:29:29 +02:00
2019-01-17 09:10:00 +01:00
app . route ( " /api/v1/search " , [ " POST " , " OPTIONS " ] , api_routes . search_v1 )
2017-05-02 18:35:34 +02:00
2019-01-17 09:10:00 +01:00
app . route ( " /api/v1/opendata " , [ " GET " , " OPTIONS " ] , api_routes . opendata_index_v1 )
2021-01-26 14:39:52 +01:00
app . route (
" /api/v1/opendata/postal_codes " ,
[ " GET " , " OPTIONS " ] ,
api_routes . opendata_postal_codes_v1 ,
)
2017-12-13 14:38:05 +01:00
2019-01-13 20:22:57 +01:00
app . route ( " /api/v1/metadata " , [ " GET " , " OPTIONS " ] , api_routes . metadata_v1 )
2021-01-26 17:31:04 +01:00
app . route ( " /api/v1/import " , [ " GET " , " OPTIONS " ] , api_routes . import_v1 )
2019-01-13 20:22:57 +01:00
2017-04-03 17:29:29 +02:00
# Index
app . route ( " / " , " GET " , lambda : _serve_static_file ( " index.html " ) )
# Static files
2021-01-26 14:39:52 +01:00
app . route ( " /favicon.ico " , " GET " , lambda : _serve_static_file ( " favicon.ico " ) )
2017-04-25 15:58:06 +02:00
app . route (
2021-01-26 14:39:52 +01:00
" /assets/<filename:path> " ,
" GET " ,
lambda filename : _serve_static_file ( " /assets/ {} " . format ( filename ) ) ,
2017-04-25 15:58:06 +02:00
)
2017-04-26 19:12:30 +02:00
app . route (
2021-01-26 14:39:52 +01:00
" /img/<filename:path> " ,
" GET " ,
lambda filename : _serve_static_file ( " /img/ {} " . format ( filename ) ) ,
2017-04-26 19:12:30 +02:00
)
2018-09-25 15:41:23 +02:00
app . route (
2021-01-26 14:39:52 +01:00
" /.well-known/<filename:path> " ,
" GET " ,
lambda filename : _serve_static_file ( " /.well-known/ {} " . format ( filename ) ) ,
2018-09-25 15:41:23 +02:00
)
2018-09-07 15:06:59 +02:00
app . route (
2021-01-26 14:39:52 +01:00
" /data/img/<filename:path> " ,
" GET " ,
2021-01-26 16:49:43 +01:00
lambda filename : bottle . static_file ( filename , root = os . path . join ( config [ " data_directory " ] , " images " ) ) ,
2018-09-07 15:06:59 +02:00
)
2017-04-03 17:29:29 +02:00
return app