Spaces:
Sleeping
Sleeping
File size: 5,297 Bytes
4e4664a 1fcd6e2 4e4664a 1fcd6e2 ce6c350 4e4664a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | """
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"
)
|