def make_api(self): self.before_hooks.extend(self.hooks.optional_request_hooks()) self.after_hooks.extend(self.hooks.optional_response_hooks()) api = API(before=self.before_hooks, after=self.after_hooks) # Set the default route to the NYI object api.add_sink(self.default_route or NYI(before=self.before_hooks, after=self.after_hooks)) # Add Error Handlers - ordered generic to more specific built_in_handlers = [(Exception, handle_unexpected_errors), (ResponseException, ResponseException.handle), (InvalidTokenError, InvalidTokenError.handle)] for ex, handler in built_in_handlers + self._error_handlers: api.add_error_handler(ex, wrap_handler_with_hooks(handler, self.after_hooks)) # Add all the routes collected thus far for _, disp in self._dispatchers.items(): for endpoint, handler in disp.get_routes(): LOG.debug("Loading endpoint %s", endpoint) api.add_route(endpoint, handler) api.add_route('%s.json' % endpoint, handler) return api
def create_api(db: Database) -> API: """Create a new application instance. - For simplicity, CORS is enabled for all origins, all methods and all headers. - ``DoesNotExist`` exceptions are caught and converted to ``404 Not Found`` error responses. Parameters ---------- db : Database An instance of the ``Database``. Returns ------- api : API """ # Middleware. cors = CORS(allow_all_origins=True, allow_all_methods=True, allow_all_headers=True) # Application instance. api = API(middleware=[cors.middleware]) # Error handlers. api.add_error_handler(DoesNotExist, on_does_not_exist) # Resources. users = UserResource(db) user_songs = UserSongsResource(db) song = SongResource(db) token = TokenResource(db) # Routes. api.add_route("/users/", users) api.add_route("/users/{username}/songs", user_songs) api.add_route("/songs/{pk}", song) api.add_route("/songs/", song) api.add_route("/tokens/{token}", token) api.add_route("/tokens/", token) return api
def api(title, version): log = Log.get('api') middlewares = [Negotiation_Middleware()] if Arg_Reader.db.auth: log.notice('JWT authentication enabled') middlewares.append( Falcon_Auth_Middleware( JWT_Auth_Backend( user_loader=lambda token: {'user': token}, secret_key=Arg_Reader.db.auth_secret_key, auth_header_prefix=Arg_Reader.db.auth_header_prefix), exempt_routes=['/api/doc', '/api/doc/swagger.json'])) else: log.notice('JWT authentication disabled') if Arg_Reader.db.https: log.notice('Force to use HTTPS instead of HTTP') middlewares.append(RequireHTTPS()) else: log.notice('HTTPS not set') if Arg_Reader.db.apm_enabled: log.notice('Elastic APM enabled') middlewares.append( Elastic_Apm_Middleware(service_name='lcp-apm', server_url=Arg_Reader.db.apm_server)) else: log.notice('Elastic APM disabled') instance = API(middleware=middlewares) media_handlers = { falcon.MEDIA_JSON: JSON_Handler(loads=loads, dumps=partial(dumps, ensure_ascii=False, sort_keys=True)), falcon.MEDIA_MSGPACK: Message_Pack_Handler(), falcon.MEDIA_XML: XML_Handler(), falcon.MEDIA_YAML: YAML_Handler() } instance.req_options.media_handlers.update(media_handlers) instance.resp_options.media_handlers.update(media_handlers) instance.add_error_handler(*Bad_Request_Handler.get()) instance.add_error_handler(*Internal_Server_Error_Handler.get()) instance.add_error_handler(*Unsupported_Media_Type_Handler.get()) api_spec = Spec(api=instance, title=title, version=version) routes(api=instance, spec=api_spec.get()) falcon_api_doc(instance, config_path='./swagger/schema.json', url_prefix='/api/doc', title='API doc') api_spec.write() return instance
def api(title, version, dev_username, dev_password): instance = API(middleware=[ Falcon_Auth_Middleware( Basic_Auth_Backend_Middleware(dev_username, dev_password), exempt_routes=['/api/doc', '/api/doc/swagger.json']), Negotiation_Middleware() # , # Elastic_Apm_Middleware( # service_name='lcp-apm', # server_url=Arg_Reader.db.apm_server # ) ]) media_handlers = { falcon.MEDIA_JSON: JSON_Handler(loads=loads, dumps=partial(dumps, ensure_ascii=False, sort_keys=True)), falcon.MEDIA_MSGPACK: Message_Pack_Handler(), falcon.MEDIA_XML: XML_Handler(), falcon.MEDIA_YAML: YAML_Handler() } instance.req_options.media_handlers.update(media_handlers) instance.resp_options.media_handlers.update(media_handlers) instance.add_error_handler(*Bad_Request_Handler.get()) instance.add_error_handler(*Unsupported_Media_Type_Handler.get()) api_spec = Spec(api=instance, title=title, version=version) routes(api=instance, spec=api_spec.get()) falcon_api_doc(instance, config_path='./swagger/schema.json', url_prefix='/api/doc', title='API doc') api_spec.write() return instance
def create_app(): # type: () -> API # Get configuration config = Configuration() logging_args = { 'level': config.log_level } if config.log_output: logging_args['filename'] = config.log_output if config.log_format: logging_args['format'] = config.log_format if config.log_style: logging_args['style'] = config.log_style if config.log_dateformat: logging_args['datefmt'] = config.log_dateformat logging.basicConfig(**logging_args) logger = logging.getLogger(__name__) # Create SQLAlchemy engine basedir = os.path.abspath(os.path.dirname(__file__)) database = '%s:///%s' % (config.db_type, os.path.join(basedir, config.db_name)) engine = create_engine(database) sql_middleware = SqlAlchemy(engine) # Drop DB if required if config.drop_db: logger.debug('Dropping current DB...') drop_db(engine) logger.debug('Current DB dropped. Recreating new DB...') else: logger.debug('Creating DB if not present') # Create DB if needed create_db(engine) logger.debug('DB created (if needed). Initializing DB content if needed.') init_db(sql_middleware.new_session(), config.matches_txt_timezone) logger.debug('DB content initialized (if needed).') sql_middleware.delete_session() # Create TimeBase service timebase = TimeBase() # Create basic authenticator for use with all Auth backend authenticator = Authenticator(timebase, sql_middleware) # Create default Token Auth backend backend = TokenAuthBackend(authenticator) # Create Falcon API with proper middleware: Marshmallow (validation), SQLAlchemy (persistence) api = API(middleware=[LoggingMiddleware(), sql_middleware, FalconAuthMiddleware(backend), context_middleware, Marshmallow()]) api.add_error_handler(Exception, ExceptionHandler(falcon.HTTP_INTERNAL_SERVER_ERROR, "Internal error")) api.add_error_handler(DBAPIError, ExceptionHandler(falcon.HTTP_INTERNAL_SERVER_ERROR, "Database error")) api.add_error_handler(IntegrityError, ExceptionHandler(falcon.HTTP_UNPROCESSABLE_ENTITY, "Integrity constraint error")) # We have to re-register the following handlers because although registered by default, # they will never get called due to our Exception handler api.add_error_handler(falcon.HTTPError, api._http_error_handler) api.add_error_handler(falcon.HTTPStatus, api._http_status_handler) from .resources import Team, Teams, Venue, Venues, Match, Matches, Bets, User, Users, Token, Time, Profile if config.timebase_changes: api.add_route('/time', Time(timebase)) api.add_route('/token', Token()) api.add_route('/team', Teams()) api.add_route('/team/{id:int}', Team()) api.add_route('/venue', Venues()) api.add_route('/venue/{id:int}', Venue()) api.add_route('/match', Matches()) api.add_route('/match/{id:int}', Match(timebase)) api.add_route('/user', Users(timebase)) api.add_route('/user/{id_or_name}', User()) api.add_route('/bet', Bets(timebase)) api.add_route('/profile', Profile(timebase)) logger.info('API service started.') return api
def install_handler(api: falcon.API) -> None: api.add_error_handler(_StructuredError)