● Zion Boggan
repos/Sightline/backend/app/main.py
zionboggan.com ↗
57 lines · python
History for this file →
1
from __future__ import annotations
2
 
3
from fastapi import FastAPI, Request
4
from fastapi.middleware.cors import CORSMiddleware
5
from fastapi.responses import JSONResponse
6
 
7
from app.api.routes import api_router
8
from app.core.config import settings
9
from app.core.rate_limit import RateLimiter
10
 
11
app = FastAPI(
12
    title=settings.app_name,
13
    version="0.1.0",
14
    description="ALPR / Flock intelligence aggregation platform - investigations, plate "
15
                "correlation, camera mapping, watchlists, reporting, OSINT enrichment.",
16
)
17
 
18
app.add_middleware(
19
    CORSMiddleware,
20
    allow_origin_regex=".*",
21
    allow_credentials=False,
22
    allow_methods=["*"],
23
    allow_headers=["*"],
24
)
25
 
26
_limiter = RateLimiter(settings.rate_limit_per_minute)
27
 
28
 
29
@app.middleware("http")
30
async def rate_limit(request: Request, call_next):
31
    path = request.url.path
32
    exempt = path.endswith("/snapshot") or path.endswith("/satellites") or "/ingest/recent" in path
33
    if path.startswith("/api/") and not exempt:
34
        client = request.client.host if request.client else "unknown"
35
        if not _limiter.allow(client):
36
            return JSONResponse(status_code=429, content={"detail": "rate limit exceeded"})
37
    return await call_next(request)
38
 
39
 
40
app.include_router(api_router, prefix="/api/v1")
41
 
42
 
43
@app.get("/health")
44
def health():
45
    return {"status": "ok", "app": settings.app_name, "env": settings.environment}
46
 
47
 
48
@app.get("/health/ready")
49
def ready():
50
    from sqlalchemy import text
51
    from app.db.session import engine
52
    try:
53
        with engine.connect() as c:
54
            c.execute(text("SELECT 1"))
55
        return {"status": "ready", "db": "ok"}
56
    except Exception as e:
57
        return JSONResponse(status_code=503, content={"status": "not_ready", "db": str(e)})