You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
SoulSync/api/__init__.py

86 lines
2.8 KiB

"""
SoulSync Public REST API (v1)
Blueprint factory + rate-limiter initialisation.
"""
from flask import Blueprint
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from utils.logging_config import get_logger
from .helpers import api_error
logger = get_logger("api_v1")
# ---------------------------------------------------------------------------
# Rate limiter (initialised with the app in web_server.py via limiter.init_app)
# ---------------------------------------------------------------------------
limiter = Limiter(
key_func=get_remote_address,
default_limits=[], # No global default — limits are applied per-blueprint
storage_uri="memory://",
)
def create_api_blueprint():
"""Build and return the /api/v1 Blueprint with all sub-modules registered."""
bp = Blueprint("api_v1", __name__)
# ---- import & register sub-module routes ----
from .library import register_routes as reg_library
from .system import register_routes as reg_system
from .search import register_routes as reg_search
from .wishlist import register_routes as reg_wishlist
from .watchlist import register_routes as reg_watchlist
from .downloads import register_routes as reg_downloads
from .playlists import register_routes as reg_playlists
from .settings import register_routes as reg_settings
from .discover import register_routes as reg_discover
from .profiles import register_routes as reg_profiles
from .retag import register_routes as reg_retag
from .listenbrainz import register_routes as reg_listenbrainz
from .cache import register_routes as reg_cache
# ---- rate-limit only /api/v1 routes (not the whole app) ----
limiter.limit("60 per minute")(bp)
reg_library(bp)
reg_system(bp)
reg_search(bp)
reg_wishlist(bp)
reg_watchlist(bp)
reg_downloads(bp)
reg_playlists(bp)
reg_settings(bp)
reg_discover(bp)
reg_profiles(bp)
reg_retag(bp)
reg_listenbrainz(bp)
reg_cache(bp)
# ---- error handlers (scoped to this Blueprint) ----
@bp.errorhandler(400)
def _bad_request(e):
return api_error("BAD_REQUEST", str(e), 400)
@bp.errorhandler(404)
def _not_found(e):
return api_error("NOT_FOUND", "Resource not found.", 404)
@bp.errorhandler(429)
def _rate_limited(e):
return api_error("RATE_LIMITED", "Too many requests. Please slow down.", 429)
@bp.errorhandler(500)
def _internal(e):
return api_error("INTERNAL_ERROR", "An internal server error occurred.", 500)
@bp.errorhandler(Exception)
def _unhandled(e):
logger.error(f"Unhandled API error: {e}", exc_info=True)
return api_error("INTERNAL_ERROR", "An unexpected error occurred.", 500)
return bp