All checks were successful
Build and Deploy MITM Webserver / build (push) Successful in 10s
133 lines
3.9 KiB
Python
133 lines
3.9 KiB
Python
"""FastAPI application entrypoint and runtime wiring."""
|
|
|
|
import asyncio
|
|
import logging
|
|
import os
|
|
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
import src.api.network_api as network_api
|
|
import src.api.sniffer_api as sniffer_api
|
|
import src.shared_objects as shared_objects
|
|
from src.api import nft_manager
|
|
from src.api import packet_api
|
|
from src.api import packet_scripting_api
|
|
from src.config import settings
|
|
from src.utilities.database import DatabasePool
|
|
from src.utilities.packet_broadcaster import PacketBroadcaster
|
|
|
|
logging.basicConfig(level=getattr(logging, settings.log_level.upper(), logging.DEBUG))
|
|
shared_objects.db = DatabasePool(
|
|
settings.db_dsn,
|
|
min_size=settings.db_pool_min_size,
|
|
max_size=settings.db_pool_max_size,
|
|
)
|
|
|
|
app = FastAPI(
|
|
root_path="/api",
|
|
title="MITM Webserver Backend",
|
|
description="Backend API for MITM Webserver",
|
|
version="1.0.0",
|
|
docs_url="/docs",
|
|
redoc_url="/redoc",
|
|
openapi_url="/openapi.json",
|
|
)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
|
|
@app.on_event("startup")
|
|
async def on_startup() -> None:
|
|
"""Initialize shared runtime objects on the FastAPI event loop."""
|
|
loop = asyncio.get_running_loop()
|
|
shared_objects.web_loop = loop
|
|
|
|
try:
|
|
await shared_objects.db.init_pool()
|
|
except Exception:
|
|
logging.exception("Failed to initialize DB pool")
|
|
raise
|
|
|
|
try:
|
|
shared_objects.broadcaster = PacketBroadcaster(loop, queue_maxsize=settings.broadcaster_queue_maxsize)
|
|
shared_objects.db.broadcaster = shared_objects.broadcaster
|
|
except Exception:
|
|
logging.exception("Failed to create/attach broadcaster")
|
|
|
|
try:
|
|
from src import network_sniffer as sniffer
|
|
|
|
try:
|
|
sniffer.drain_buffer_to_shared_db()
|
|
except Exception:
|
|
logging.exception("Failed to drain sniffer buffer")
|
|
except ImportError:
|
|
logging.debug("Sniffer module not importable at startup; skipping buffer drain")
|
|
|
|
|
|
@app.on_event("shutdown")
|
|
async def shutdown_event() -> None:
|
|
"""Stop network resources and release shared runtime objects."""
|
|
try:
|
|
network_api.shutdown_network_api()
|
|
except Exception:
|
|
logging.exception("Error shutting down network API")
|
|
|
|
try:
|
|
from src.utilities.bridge_telemetry import bridge_telemetry_manager
|
|
|
|
bridge_telemetry_manager.stop()
|
|
except Exception:
|
|
logging.exception("Failed to stop bridge telemetry collector")
|
|
|
|
try:
|
|
from src.utilities.packet_tracker import packet_tracker
|
|
|
|
packet_tracker.stop()
|
|
except Exception:
|
|
logging.exception("Failed to stop packet tracker")
|
|
|
|
try:
|
|
if shared_objects.broadcaster is not None:
|
|
await shared_objects.broadcaster.close()
|
|
except Exception:
|
|
logging.exception("Failed to close packet broadcaster during shutdown")
|
|
|
|
try:
|
|
web_db = getattr(shared_objects, "db", None)
|
|
if web_db is not None:
|
|
await web_db.close_pool()
|
|
except Exception:
|
|
logging.exception("Failed to close DB pool during shutdown")
|
|
|
|
shared_objects.db = None
|
|
shared_objects.broadcaster = None
|
|
shared_objects.web_loop = None
|
|
|
|
|
|
@app.get("/hello")
|
|
def hello() -> dict[str, str]:
|
|
"""Simple health-check endpoint."""
|
|
return {"message": "Hello from FastAPI 🎉"}
|
|
|
|
|
|
@app.get("/versions")
|
|
def versions() -> dict[str, str]:
|
|
"""Return runtime Python version."""
|
|
message = os.popen("python --version").read().strip()
|
|
return {"message": message}
|
|
|
|
|
|
app.include_router(network_api.router, prefix="/network", tags=["network"])
|
|
app.include_router(sniffer_api.router, prefix="/sniffer", tags=["sniffer"])
|
|
app.include_router(packet_api.router, prefix="/packets", tags=["packets"])
|
|
app.include_router(nft_manager.router, tags=["firewall"])
|
|
app.include_router(packet_scripting_api.router, prefix="/scripts", tags=["scripts"])
|