Spaces:
Runtime error
Runtime error
Download app.py from MusinguziBenard/face-recognition-api: direct link, hf CLI and curl.
- Browser
- Download file 4.26 kB
-
https://huggingface.co/spaces/MusinguziBenard/face-recognition-api/resolve/main/app.py
- Command line
-
hf download hf://spaces/MusinguziBenard/face-recognition-api/app.py
-
curl -L -o app.py https://huggingface.co/spaces/MusinguziBenard/face-recognition-api/resolve/main/app.py
4.26 kB
| # app.py | |
| from fastapi import FastAPI, Request, HTTPException | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import JSONResponse | |
| import logging | |
| import time | |
| from api.health import router as health_router | |
| from api.extract import router as extract_router | |
| from api.enroll import router as enroll_router | |
| from api.recognize import router as recognize_router | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' | |
| ) | |
| logger = logging.getLogger(__name__) | |
| app = FastAPI( | |
| title="SchoolMaster Face Recognition Service", | |
| description="AI face recognition for school attendance", | |
| version="1.0.0" | |
| ) | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| async def log_requests(request: Request, call_next): | |
| start_time = time.time() | |
| response = await call_next(request) | |
| process_time = time.time() - start_time | |
| logger.info(f"{request.method} {request.url.path} - {response.status_code} - {process_time:.3f}s") | |
| return response | |
| async def root(): | |
| return { | |
| "service": "SchoolMaster Face Recognition", | |
| "status": "running", | |
| "version": "1.0.0", | |
| "endpoints": [ | |
| "GET /api/health", | |
| "POST /api/extract", | |
| "POST /api/enroll", | |
| "POST /api/recognize" | |
| ] | |
| } | |
| app.include_router(health_router, prefix="/api", tags=["Health"]) | |
| app.include_router(extract_router, prefix="/api", tags=["Extraction"]) | |
| app.include_router(enroll_router, prefix="/api", tags=["Enrollment"]) | |
| app.include_router(recognize_router, prefix="/api", tags=["Recognition"]) | |
| async def http_exception_handler(request, exc): | |
| return JSONResponse( | |
| status_code=exc.status_code, | |
| content={"success": False, "message": exc.detail} | |
| ) | |
| # ============================================================ | |
| # Minimal Gradio status page, mounted onto the SAME app/port. | |
| # This is only here so the Space genuinely uses the Gradio SDK | |
| # (keeping it eligible for free hosting) - your PHP backend | |
| # talks to the /api/* routes above directly and never touches this UI. | |
| # | |
| # Wrapped defensively: if Gradio itself fails to import or mount for | |
| # any reason (version mismatches inside HF's build environment have | |
| # happened before), the actual API - the thing PHP depends on - must | |
| # still start and serve requests. A broken status page should never | |
| # be able to take down the real service. | |
| # ============================================================ | |
| try: | |
| import gradio as gr | |
| import requests as _requests | |
| def check_health(): | |
| try: | |
| r = _requests.get(f"http://127.0.0.1:{7860}/api/health", timeout=5) | |
| return r.json() | |
| except Exception as e: | |
| return {"error": str(e)} | |
| with gr.Blocks(title="Face Recognition API") as demo: | |
| gr.Markdown( | |
| "# Face Recognition API\n\n" | |
| "This is a status page only. Your school system's PHP backend talks " | |
| "directly to the `/api/*` endpoints below - nothing here.\n\n" | |
| "**Endpoints:** `/api/health` (GET), `/api/extract`, `/api/enroll`, " | |
| "`/api/recognize` (POST, require `X-API-Key` header + multipart photos)" | |
| ) | |
| btn = gr.Button("Check API Health", variant="primary") | |
| out = gr.JSON(label="Result") | |
| btn.click(fn=check_health, outputs=out) | |
| app = gr.mount_gradio_app(app, demo, path="/ui") | |
| logger.info("Gradio status page mounted at /ui") | |
| except Exception as e: | |
| logger.warning(f"Gradio status page failed to load, continuing without it: {e}") | |
| if __name__ == "__main__": | |
| import uvicorn | |
| from config import Config | |
| # Hugging Face Spaces health-checks port 7860 specifically - hardcoded | |
| # here (not from Config.PORT/env) so a stray PORT variable in the | |
| # Space's settings can never silently break this again. | |
| SPACES_PORT = 7860 | |
| uvicorn.run( | |
| app, | |
| host=Config.HOST, | |
| port=SPACES_PORT, | |
| ) |