123 lines
3.8 KiB
Python
123 lines
3.8 KiB
Python
from fastapi import FastAPI, Request, HTTPException
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import JSONResponse, HTMLResponse
|
|
from fastapi.staticfiles import StaticFiles
|
|
from fastapi.templating import Jinja2Templates
|
|
import os
|
|
import uvicorn
|
|
from loguru import logger
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from app.core.config import settings
|
|
from app.api.routes import router as api_router
|
|
|
|
# Configure logging
|
|
logger.remove()
|
|
logger.add(
|
|
sys.stdout,
|
|
format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}",
|
|
level="DEBUG" if settings.DEBUG else "INFO",
|
|
)
|
|
|
|
# Create FastAPI app
|
|
app = FastAPI(
|
|
title=settings.APP_NAME,
|
|
version=settings.APP_VERSION,
|
|
description="A lightweight document compliance and validation tool",
|
|
docs_url="/docs",
|
|
redoc_url="/redoc",
|
|
openapi_url="/openapi.json",
|
|
)
|
|
|
|
# Add CORS middleware
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"], # In production, this should be restricted
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# Create templates directory
|
|
templates_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "templates")
|
|
os.makedirs(templates_dir, exist_ok=True)
|
|
templates = Jinja2Templates(directory=templates_dir)
|
|
|
|
# Create static files directory if it doesn't exist
|
|
static_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "static")
|
|
if not os.path.exists(static_dir):
|
|
os.makedirs(static_dir, exist_ok=True)
|
|
|
|
# Ensure CSS and JS directories exist
|
|
css_dir = os.path.join(static_dir, "css")
|
|
js_dir = os.path.join(static_dir, "js")
|
|
os.makedirs(css_dir, exist_ok=True)
|
|
os.makedirs(js_dir, exist_ok=True)
|
|
|
|
# Mount static files
|
|
app.mount("/static", StaticFiles(directory=static_dir), name="static")
|
|
|
|
# Include API routes
|
|
app.include_router(api_router, prefix="/api")
|
|
|
|
# Root endpoint - serve the frontend
|
|
@app.get("/", response_class=HTMLResponse)
|
|
async def root(request: Request):
|
|
# Check if index.html exists in static directory
|
|
index_path = os.path.join(static_dir, "index.html")
|
|
|
|
if os.path.exists(index_path):
|
|
with open(index_path, "r") as f:
|
|
return HTMLResponse(content=f.read())
|
|
|
|
# If not found, return a simple HTML response
|
|
return HTMLResponse(
|
|
content=f"""
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>{settings.APP_NAME}</title>
|
|
<style>
|
|
body {{ font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }}
|
|
h1 {{ color: #3498db; }}
|
|
.api-link {{ margin-top: 20px; }}
|
|
.api-link a {{ display: inline-block; padding: 10px 20px; background-color: #3498db; color: white;
|
|
text-decoration: none; border-radius: 4px; }}
|
|
.api-link a:hover {{ background-color: #2980b9; }}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>{settings.APP_NAME}</h1>
|
|
<p>Welcome to {settings.APP_NAME}, a lightweight document compliance and validation tool.</p>
|
|
<p>This application is currently running in API-only mode.</p>
|
|
<div class="api-link">
|
|
<a href="/docs">View API Documentation</a>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
"""
|
|
)
|
|
|
|
# Health check endpoint
|
|
@app.get("/health")
|
|
async def health():
|
|
return {"status": "healthy"}
|
|
|
|
# Global exception handler
|
|
@app.exception_handler(Exception)
|
|
async def global_exception_handler(request: Request, exc: Exception):
|
|
logger.error(f"Unhandled exception: {str(exc)}")
|
|
return JSONResponse(
|
|
status_code=500,
|
|
content={"message": "An unexpected error occurred", "detail": str(exc)},
|
|
)
|
|
|
|
if __name__ == "__main__":
|
|
uvicorn.run(
|
|
"app.main:app",
|
|
host="0.0.0.0",
|
|
port=8000,
|
|
reload=settings.DEBUG,
|
|
log_level="debug" if settings.DEBUG else "info",
|
|
) |