File size: 6,373 Bytes
7616a39 52f18dd 7616a39 c1b303d 7616a39 52f18dd 7616a39 c1b303d 7616a39 54c31ea c1b303d d3fed97 538360f 86992c4 c7aa14e 9929084 6f77b72 52f18dd 538360f 52f18dd 7616a39 52f18dd 7616a39 52f18dd 7616a39 52f18dd 7616a39 54c31ea d3fed97 c1b303d 538360f 86992c4 c7aa14e 9929084 6f77b72 c7aa14e 52f18dd 7616a39 52f18dd 7616a39 52f18dd 7616a39 52f18dd 7616a39 4c94669 7616a39 52f18dd 7616a39 5715faa 52f18dd 507fdbe 7616a39 5715faa 507fdbe 7616a39 5715faa |
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 |
"""
Main FastAPI application module.
"""
import os
import time
import logging
import json
from datetime import datetime
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from contextlib import asynccontextmanager
import warnings
from app.page_speed.config import settings
from app.page_speed.models import HealthResponse
from app.rag.routes import router as rag_router
from app.seo import routes as seo_routes
from app.page_speed import routes as page_speed_routes
from app.content_relevence import routes as content_relevance_routes
from app.keywords.routes import router as keywords_router
from app.uiux import routes as uiux_routes
from app.mobile_usability import routes as mobile_usability
from app.ads.persona_routes import router as persona_router
# βββββββββββββββββββββββββββββββββββββββββββββ
# Suppress warnings
# βββββββββββββββββββββββββββββββββββββββββββββ
warnings.filterwarnings(
"ignore",
message="Valid config keys have changed in V2:*",
category=UserWarning,
module="pydantic._internal._config",
)
warnings.filterwarnings("ignore", category=FutureWarning)
try:
from langchain_core._api.deprecation import LangChainDeprecationWarning
warnings.filterwarnings("ignore", category=LangChainDeprecationWarning)
except ImportError:
pass
# βββββββββββββββββββββββββββββββββββββββββββββ
# Logging setup
# βββββββββββββββββββββββββββββββββββββββββββββ
logger = logging.getLogger("app")
logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
formatter = logging.Formatter(
"%(asctime)s | %(levelname)s | %(name)s | %(message)s",
datefmt="%Y-%m-%d %H:%M:%S"
)
handler.setFormatter(formatter)
logger.addHandler(handler)
startup_time = None
@asynccontextmanager
async def lifespan(app: FastAPI):
global startup_time
startup_time = time.time()
logger.info("π Starting %s v%s", settings.app_name, settings.app_version)
logger.info("π Server will run on %s:%s", settings.host, settings.port)
yield
logger.info("π Shutting down %s", settings.app_name)
# βββββββββββββββββββββββββββββββββββββββββββββ
# FastAPI app creation
# βββββββββββββββββββββββββββββββββββββββββββββ
app = FastAPI(
title=settings.app_name,
description=settings.app_description,
version=settings.app_version,
lifespan=lifespan,
docs_url="/docs",
redoc_url="/redoc"
)
# Include routers
app.include_router(rag_router)
app.include_router(seo_routes.router)
app.include_router(content_relevance_routes.router)
app.include_router(page_speed_routes.router)
app.include_router(keywords_router)
app.include_router(uiux_routes.router)
app.include_router(mobile_usability.router)
app.include_router(persona_router)
# CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # TODO: Restrict in production
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# βββββββββββββββββββββββββββββββββββββββββββββ
# Routes
# βββββββββββββββββββββββββββββββββββββββββββββ
@app.get("/", response_model=dict)
async def root():
return {
"message": f"Welcome to {settings.app_name}",
"version": settings.app_version,
"description": settings.app_description,
"docs": "/docs",
"health": "/health"
}
@app.get("/health", response_model=HealthResponse)
async def health_check():
if startup_time:
uptime_seconds = time.time() - startup_time
uptime_str = f"{uptime_seconds:.2f} seconds"
else:
uptime_str = "Unknown"
return HealthResponse(
status="healthy",
version=settings.app_version,
uptime=uptime_str
)
# from app.rag.utils import cleanup_old_vectorstores
# @asynccontextmanager
# async def lifespan(app: FastAPI):
# global startup_time
# startup_time = time.time()
# logger.info("π Starting %s v%s", settings.app_name, settings.app_version)
# logger.info("π Server will run on %s:%s", settings.host, settings.port)
# # Trigger cleanup on startup
# deleted = cleanup_old_vectorstores(days=7)
# logger.info("π§Ή Cleanup complete. %s old sessions removed.", deleted)
# yield
# logger.info("π Shutting down %s", settings.app_name)
@app.exception_handler(404)
async def not_found_handler(request, exc):
logger.warning("404 Not Found: %s %s", request.method, request.url.path)
return JSONResponse(
status_code=404,
content={
"error": "Not Found",
"message": "The requested endpoint was not found",
"docs": "/docs"
}
)
@app.exception_handler(500)
async def internal_error_handler(request, exc):
logger.error("500 Internal Server Error: %s %s -> %s", request.method, request.url.path, exc, exc_info=True)
return JSONResponse(
status_code=500,
content={
"error": "Internal Server Error",
"message": "An unexpected error occurred",
"timestamp": datetime.now().isoformat()
}
)
# βββββββββββββββββββββββββββββββββββββββββββββ
# Entrypoint
# βββββββββββββββββββββββββββββββββββββββββββββ
if __name__ == "__main__":
import uvicorn
import os
# Default to 7860 (Hugging Face standard) instead of 8080
port = int(os.environ.get("PORT", 7860))
uvicorn.run(
"app.main:app",
host="0.0.0.0",
port=port,
reload=False # optimizing for production
)
|