feat(server): FastAPI app with API-key auth and health check
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
37
server/app.py
Normal file
37
server/app.py
Normal file
@@ -0,0 +1,37 @@
|
||||
"""MusicFetch REST API. Plain HTTP behind an upstream TLS reverse proxy."""
|
||||
import os
|
||||
|
||||
from fastapi import Depends, FastAPI, Header, HTTPException
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from . import actions, jobs, mf
|
||||
|
||||
API_KEY = os.environ.get("MUSICFETCH_API_KEY", "")
|
||||
ROOT = os.environ.get("MUSICFETCH_ROOT", "/media/music")
|
||||
|
||||
app = FastAPI(title="MusicFetch API")
|
||||
|
||||
|
||||
def require_key(x_api_key: str = Header(default="")):
|
||||
if not API_KEY or x_api_key != API_KEY:
|
||||
raise HTTPException(status_code=401, detail="Invalid API key.")
|
||||
|
||||
|
||||
@app.exception_handler(HTTPException)
|
||||
async def _http_exc(_req, exc: HTTPException):
|
||||
# Always return a Siri-speakable {"message": ...} body.
|
||||
return JSONResponse(status_code=exc.status_code, content={"message": exc.detail})
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
def health():
|
||||
return {"status": "ok"}
|
||||
|
||||
|
||||
# Minimal stub so that auth tests can verify 401 behaviour before the real
|
||||
# /fetch implementation lands in Task 5. This route MUST carry require_key as
|
||||
# a dependency so unauthenticated / wrong-key requests are rejected here.
|
||||
@app.post("/fetch", dependencies=[Depends(require_key)])
|
||||
def fetch_stub(q: str = ""):
|
||||
# Task 5 will replace this body with the full search-and-download logic.
|
||||
raise HTTPException(status_code=501, detail="Not yet implemented.")
|
||||
Reference in New Issue
Block a user