""" Production-Ready FastAPI Application Real Estate Tokenization Platform - AtriumChain Platform """ from fastapi import FastAPI, status, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware from fastapi.responses import JSONResponse from contextlib import asynccontextmanager from slowapi import _rate_limit_exceeded_handler from slowapi.errors import RateLimitExceeded from config import settings from db import init_mongo, close_mongo, check_db_health from utils.logger import setup_logging from middleware.security import SecurityHeadersMiddleware, RequestIDMiddleware, limiter # Import routes from routes import ( auth, otp, properties, market, wallet, portfolio, admin, super_admin, secondary_market, profile ) @asynccontextmanager async def lifespan(app: FastAPI): """Application lifespan events""" print("\n" + "="*80) print("STARTING REAL ESTATE TOKENIZATION PLATFORM") print("="*80 + "\n") # Startup try: # Initialize logging system setup_logging() print("[APP] ✅ Logging system initialized") db = init_mongo(app) print("[APP] ✅ Application startup complete\n") except Exception as e: print(f"[APP] [ERROR] Startup failed: {str(e)}\n") raise yield # Shutdown print("\n[APP] Shutting down...") close_mongo() print("[APP] ✅ Shutdown complete\n") # Create FastAPI app app = FastAPI( title="Real Estate Tokenization Platform", description="Production-ready platform for fractional real estate investment using blockchain", version="2.0.0", lifespan=lifespan ) # Add HTTPS redirect middleware in production if settings.is_production(): app.add_middleware(HTTPSRedirectMiddleware) print("[APP] ✅ HTTPS enforcement enabled (production mode)") # Add security middleware app.add_middleware(SecurityHeadersMiddleware) app.add_middleware(RequestIDMiddleware) # Add rate limiter app.state.limiter = limiter app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler) # CORS middleware app.add_middleware( CORSMiddleware, allow_origins=settings.CORS_ORIGINS, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Health check endpoint @app.get("/", tags=["Health"]) async def root(): """Root endpoint - API health check""" return { "message": "🚀 AtriumChain Backend Started Successfully!", "status": "online", "service": "Real Estate Tokenization Platform", "version": "2.0.0", "environment": settings.XRPL_NETWORK, "docs": "/" } @app.get("/health", tags=["Health"]) async def health_check(): """Detailed health check including database connectivity""" db_health = check_db_health() return { "status": "healthy" if db_health["status"] == "healthy" else "degraded", "api": "online", "database": db_health } # Include routers app.include_router( auth.router, prefix="/api/v1/auth", tags=["Authentication"] ) app.include_router( otp.router, prefix="/api/v1/otp", tags=["OTP Verification"] ) app.include_router( properties.router, prefix="/api/v1", tags=["Properties"] ) app.include_router( market.router, prefix="/api/v1", tags=["Market"] ) app.include_router( secondary_market.router, prefix="/api/v1", tags=["Secondary Market"] ) app.include_router( wallet.router, prefix="/api/v1", tags=["Wallet"] ) app.include_router( portfolio.router, prefix="/api/v1", tags=["Portfolio"] ) app.include_router( admin.router, prefix="/api/v1", tags=["Admin"] ) app.include_router( super_admin.router, prefix="/api/v1", tags=["Super Admin"] ) app.include_router( profile.router, prefix="/api/v1/profile", tags=["Profile"] ) # Global exception handler (sanitized) @app.exception_handler(Exception) async def global_exception_handler(request, exc): """Handle all unhandled exceptions (hide internals in production).""" # Use structured logging instead of print import logging logger = logging.getLogger(__name__) logger.error(f"Unhandled exception: {exc.__class__.__name__}: {str(exc)}", exc_info=settings.is_development()) return JSONResponse( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content={ "detail": "An unexpected error occurred. Please try again later.", "error": str(exc) if settings.is_development() else "Internal server error" } ) # Run with: uvicorn main:app --reload --port 8000 if __name__ == "__main__": import uvicorn print("\n" + "="*80) print("DEVELOPMENT SERVER (LOCAL ONLY)") print("="*80) print("Starting server on http://127.0.0.1:8000") print("API Documentation: http://127.0.0.1:8000/docs") print("NOTE: For production, use: uvicorn main:app --host 0.0.0.0 --port 8000") print("="*80 + "\n") uvicorn.run( "main:app", host="0.0.0.0", # Bind to localhost only for development security port=8000, reload=True, log_level="info" )