misc
This commit is contained in:
69
base.py
69
base.py
@@ -4,6 +4,7 @@ import sys
|
||||
sys.path.insert(0, ".")
|
||||
import logging
|
||||
import asyncio
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import Any
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
@@ -13,20 +14,61 @@ from lyric_search.sources import redis_cache
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logging.getLogger("aiosqlite").setLevel(logging.WARNING)
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
logging.getLogger("python_multipart.multipart").setLevel(logging.WARNING)
|
||||
logging.getLogger("streamrip").setLevel(logging.WARNING)
|
||||
logging.getLogger("utils.sr_wrapper").setLevel(logging.WARNING)
|
||||
logger = logging.getLogger()
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
# Pre-import endpoint modules so we can wire up lifespan
|
||||
constants = importlib.import_module("constants").Constants()
|
||||
|
||||
# Will be set after app creation
|
||||
_routes: dict = {}
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
"""Lifespan context manager for startup/shutdown events."""
|
||||
# Startup
|
||||
uvicorn_access_logger = logging.getLogger("uvicorn.access")
|
||||
uvicorn_access_logger.disabled = True
|
||||
|
||||
# Start Radio playlists
|
||||
if "radio" in _routes and hasattr(_routes["radio"], "on_start"):
|
||||
await _routes["radio"].on_start()
|
||||
|
||||
# Start endpoint background tasks
|
||||
if "trip" in _routes and hasattr(_routes["trip"], "startup"):
|
||||
await _routes["trip"].startup()
|
||||
if "lighting" in _routes and hasattr(_routes["lighting"], "startup"):
|
||||
await _routes["lighting"].startup()
|
||||
|
||||
logger.info("Application startup complete")
|
||||
|
||||
yield
|
||||
|
||||
# Shutdown
|
||||
if "lighting" in _routes and hasattr(_routes["lighting"], "shutdown"):
|
||||
await _routes["lighting"].shutdown()
|
||||
if "trip" in _routes and hasattr(_routes["trip"], "shutdown"):
|
||||
await _routes["trip"].shutdown()
|
||||
|
||||
logger.info("Application shutdown complete")
|
||||
|
||||
|
||||
app = FastAPI(
|
||||
title="codey.lol API",
|
||||
version="1.0",
|
||||
contact={"name": "codey"},
|
||||
redirect_slashes=False,
|
||||
loop=loop,
|
||||
docs_url="/docs", # Swagger UI (default)
|
||||
redoc_url="/redoc", # ReDoc UI (default, but explicitly set)
|
||||
docs_url=None, # Disabled - using Scalar at /docs instead
|
||||
redoc_url="/redoc",
|
||||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
constants = importlib.import_module("constants").Constants()
|
||||
util = importlib.import_module("util").Utilities(app, constants)
|
||||
|
||||
origins = [
|
||||
@@ -48,8 +90,8 @@ app.add_middleware(
|
||||
) # type: ignore
|
||||
|
||||
|
||||
# Add Scalar API documentation endpoint (before blacklist routes)
|
||||
@app.get("/scalar", include_in_schema=False)
|
||||
# Scalar API documentation at /docs (replaces default Swagger UI)
|
||||
@app.get("/docs", include_in_schema=False)
|
||||
def scalar_docs():
|
||||
return get_scalar_api_reference(openapi_url="/openapi.json", title="codey.lol API")
|
||||
|
||||
@@ -72,7 +114,7 @@ def base_head():
|
||||
@app.get("/{path}", include_in_schema=False)
|
||||
def disallow_get_any(request: Request, var: Any = None):
|
||||
path = request.path_params["path"]
|
||||
allowed_paths = ["widget", "misc/no", "docs", "redoc", "scalar", "openapi.json"]
|
||||
allowed_paths = ["widget", "misc/no", "docs", "redoc", "openapi.json"]
|
||||
logging.info(
|
||||
f"Checking path: {path}, allowed: {path in allowed_paths or path.split('/', maxsplit=1)[0] in allowed_paths}"
|
||||
)
|
||||
@@ -99,7 +141,7 @@ End Blacklisted Routes
|
||||
Actionable Routes
|
||||
"""
|
||||
|
||||
routes: dict = {
|
||||
_routes.update({
|
||||
"randmsg": importlib.import_module("endpoints.rand_msg").RandMsg(
|
||||
app, util, constants
|
||||
),
|
||||
@@ -116,12 +158,12 @@ routes: dict = {
|
||||
"lighting": importlib.import_module("endpoints.lighting").Lighting(
|
||||
app, util, constants
|
||||
),
|
||||
}
|
||||
})
|
||||
|
||||
# Misc endpoint depends on radio endpoint instance
|
||||
radio_endpoint = routes.get("radio")
|
||||
radio_endpoint = _routes.get("radio")
|
||||
if radio_endpoint:
|
||||
routes["misc"] = importlib.import_module("endpoints.misc").Misc(
|
||||
_routes["misc"] = importlib.import_module("endpoints.misc").Misc(
|
||||
app, util, constants, radio_endpoint
|
||||
)
|
||||
|
||||
@@ -133,12 +175,5 @@ End Actionable Routes
|
||||
Startup
|
||||
"""
|
||||
|
||||
|
||||
async def on_start():
|
||||
uvicorn_access_logger = logging.getLogger("uvicorn.access")
|
||||
uvicorn_access_logger.disabled = True
|
||||
|
||||
|
||||
app.add_event_handler("startup", on_start)
|
||||
redis = redis_cache.RedisCache()
|
||||
loop.create_task(redis.create_index())
|
||||
|
||||
Reference in New Issue
Block a user