hibatorrahmen's picture
added fixes
1d14811
import uvicorn
from fastapi import FastAPI, APIRouter, Request, Depends, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
import asyncio
from concurrent.futures import ThreadPoolExecutor
from fastapi.responses import JSONResponse
import logging
import time
import os
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import jwt
from typing import Optional
from app.core.config import settings
from app.api.routes.videos import router as videos_router
from app.api.routes.auth import router as auth_router
from app.api.routes.processing import router as processing_router
from app.api.routes.users import router as users_router
from app.api.routes.health import router as health_router
from app.db.base import create_tables
# Create database tables
create_tables()
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Add security scheme
security = HTTPBearer(auto_error=False)
# Add authentication dependency
async def verify_token(request: Request, credentials: Optional[HTTPAuthorizationCredentials] = Depends(security)):
# First check for HF Space JWT token in query params
hf_token = request.query_params.get("__sign")
if hf_token:
try:
# Verify the JWT token (you may want to add more verification)
jwt.decode(hf_token, options={"verify_signature": False})
return hf_token
except jwt.InvalidTokenError:
raise HTTPException(status_code=403, detail="Invalid HF Space token")
# Then check for Bearer token
if credentials:
token = credentials.credentials
if not token:
raise HTTPException(
status_code=401,
detail="Invalid authentication credentials",
headers={"WWW-Authenticate": "Bearer"},
)
return token
# If no token found at all
raise HTTPException(
status_code=401,
detail="Authentication required",
headers={"WWW-Authenticate": "Bearer"},
)
# Create FastAPI app
app = FastAPI(
title="Behavior Analytics API",
description="API for behavior analytics processing",
version="1.0.0",
docs_url="/docs", # Swagger UI
redoc_url="/redoc", # ReDoc UI
# Disable automatic redirect for trailing slashes
redirect_slashes=False
)
# Configure CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Allow all origins for testing
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Mount static files
app.mount("/uploads", StaticFiles(directory=str(settings.UPLOAD_DIR)), name="uploads")
# Create main API router
api_router = APIRouter()
# Include all routers except health
api_router.include_router(videos_router)
api_router.include_router(processing_router)
api_router.include_router(users_router)
api_router.include_router(auth_router)
# Include API router in app
app.include_router(api_router, prefix=settings.API_V1_STR)
# Mount health router directly to app
app.include_router(health_router)
@app.middleware("http")
async def log_requests(request: Request, call_next):
"""Log all requests and their processing time"""
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
logger.info(f"Path: {request.url.path} Method: {request.method} Time: {process_time:.2f}s Status: {response.status_code}")
return response
@app.get("/")
async def root(token: str = Depends(verify_token)):
"""Root endpoint that returns API status"""
return {
"status": "ok",
"message": "Behavior Analytics API is running",
"version": "1.0.0"
}
@app.get("/health")
async def health_check():
"""Health check endpoint for Hugging Face Spaces"""
return {"status": "ok"}
@app.on_event("shutdown")
async def shutdown_event():
loop = asyncio.get_running_loop()
with ThreadPoolExecutor() as pool:
await loop.run_in_executor(pool, shutdown_tasks)
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=7860, reload=True)