from fastapi import FastAPI from contextlib import asynccontextmanager from fastapi.staticfiles import StaticFiles from fastapi.middleware.gzip import GZipMiddleware from app.controllers.route_to_web import RouteToWeb from app.services.markdown_processor import MarkdownProcessor from app.services.metadata_processor import MetadataProcessor from app.controllers.category_controller import CategoryController class CustomStaticFiles(StaticFiles): """Custom StaticFiles class to add cache headers.""" def __init__(self, directory: str, cache_timeout: int = 31536000): """ Initialize the custom static files handler. :param directory: Directory containing static files. :param cache_timeout: Cache timeout in seconds (default: 1 year). """ super().__init__(directory=directory) self.cache_timeout = cache_timeout async def get_response(self, path: str, scope): """Override to add custom cache headers.""" response = await super().get_response(path, scope) response.headers["Cache-Control"] = f"public, max-age={self.cache_timeout}, immutable" return response class Application: def __init__(self): """Initialize the FastAPI app and configure it.""" self.app = FastAPI(lifespan=self._lifespan_event) self._setup_static_files() self._include_routers() self._include_middleware() @asynccontextmanager async def _lifespan_event(self, app: FastAPI): """Lifespan event for startup and shutdown logic.""" print("App startup: Processing Markdown files...") # Generate dynamic JSON data metadata_processor = MetadataProcessor(input_dir="./data", output_file="generated_data.json") metadata_processor.generate_json() print("Generated dynamic data file.") print("Markdown processing complete!") # Process Markdown files into HTML processor = MarkdownProcessor(input_dir="./data", templates_dir="./templates") processor.run() yield print("App shutdown: Cleanup complete.") def _setup_static_files(self): """Mount static file directories with caching.""" self.app.mount("/data", CustomStaticFiles(directory="data"), name="data") self.app.mount("/static", CustomStaticFiles(directory="static"), name="static") self.app.mount("/images", CustomStaticFiles(directory="static/images"), name="img") def _include_routers(self): """Include all route controllers.""" category_controller = CategoryController() route_to_web = RouteToWeb(self.app) self.app.include_router(category_controller.router) self.app.include_router(route_to_web.router) def _include_middleware(self): """Add middleware for compression and other features.""" self.app.add_middleware(GZipMiddleware, minimum_size=500) def get_app(self): """Return the FastAPI app instance.""" return self.app application = Application() app = application.get_app()