#!/usr/bin/env python3 """ OpenEventDatabase Backend This is the main entry point for the OpenEventDatabase backend. It initializes the Falcon application and sets up the routes. """ import sys import os import falcon # Import utility modules from oedb.utils.logging import logger from oedb.utils.db import check_db_connection, load_env_from_file # Import middleware from oedb.middleware.headers import HeaderMiddleware from oedb.middleware.cache import CacheMiddleware from oedb.middleware.rate_limit import RateLimitMiddleware # Import resources from oedb.resources.event import event from oedb.resources.stats import StatsResource from oedb.resources.search import EventSearch from oedb.resources.root import root from oedb.resources.demo import demo, demo_stats from oedb.resources.live import live from oedb.resources.rss import rss_latest, rss_by_family from oedb.resources.event_form import event_form from oedb.resources.db_dump import db_dump_list, db_dump_create from oedb.resources.quality_assurance import quality_assurance def create_app(): """ Create and configure the Falcon application. Returns: falcon.App: The configured Falcon application. """ # Load environment variables from .env (if present) load_env_from_file() # Create the Falcon application with middleware logger.info("Initializing Falcon application") app = falcon.App(middleware=[ HeaderMiddleware(), CacheMiddleware(), RateLimitMiddleware() ]) # Add static file serving logger.info("Setting up static file serving") static_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'oedb', 'resources', 'demo', 'static')) app.add_static_route('/static/', static_dir) # Check environment variables required_env = [ 'DB_NAME', 'DB_HOST', 'DB_USER', 'POSTGRES_PASSWORD', 'CLIENT_ID', 'CLIENT_SECRET', 'CLIENT_REDIRECT', 'CLIENT_AUTHORIZATIONS' ] optional_env = [ 'PANORAMAX_UPLOAD_URL', 'PANORAMAX_TOKEN' ] missing_required = [k for k in required_env if not os.getenv(k)] missing_optional = [k for k in optional_env if not os.getenv(k)] if missing_required: logger.warning(f"Missing required environment variables: {', '.join(missing_required)}") if missing_optional: logger.info(f"Optional environment variables not set: {', '.join(missing_optional)}") # Check database connection before continuing if not check_db_connection(): logger.error("Cannot start server - PostgreSQL database is not responding") sys.exit(1) # Create resource instances stats = StatsResource() event_search = EventSearch() # Add routes logger.info("Setting up API routes") app.add_route('/', root) # Handle root requests app.add_route('/event/search', event_search) # Handle event search requests app.add_route('/event/{id}', event) # Handle single event requests app.add_route('/event', event) # Handle event collection requests app.add_route('/stats', stats) # Handle stats requests app.add_route('/quality_assurance', quality_assurance) # Handle quality assurance requests app.add_route('/demo', demo) # Handle demo page requests app.add_route('/demo/add', event_form) # Handle event submission form app.add_route('/demo/by-what', demo, suffix='by_what') # Handle events by type page app.add_route('/demo/map-by-what', demo, suffix='map_by_what') # Handle map by event type page app.add_route('/demo/map-by-what/{event_type}', demo, suffix='map_by_what_type') # Handle map by specific event type app.add_route('/demo/edit/{id}', demo, suffix='edit') # Handle event editing page app.add_route('/demo/by_id/{id}', demo, suffix='by_id') # Handle view single event by id app.add_route('/demo/traffic', demo, suffix='traffic') # Handle traffic jam reporting page app.add_route('/demo/view-events', demo, suffix='view_events') # Handle view saved events page app.add_route('/demo/stats', demo_stats) # Handle stats by what page app.add_route('/demo/property-stats', demo, suffix='property_stats') # Handle property statistics page app.add_route('/demo/live', live) # Live page app.add_route('/rss', rss_latest) # RSS latest 200 app.add_route('/rss/by/{family}', rss_by_family) # RSS by family app.add_route('/db/dumps', db_dump_list) # List database dumps app.add_route('/db/dumps/create', db_dump_create) # Create database dumps logger.success("Application initialized successfully") return app # Create the WSGI application app = create_app() if __name__ == '__main__': # This block is executed when the script is run directly import waitress logger.info(" -------------- Starting server on http://127.0.0.1:8080 ------------") waitress.serve(app, host='127.0.0.1', port=8080)