MediaRouter / app /api /media.py
basyx's picture
Upload 340 files
3493993 verified
Raw
History Blame Contribute Delete
2.6 kB
from __future__ import annotations
from collections.abc import AsyncIterator
from pathlib import Path
import aiofiles
from fastapi import APIRouter, Request
from fastapi.responses import StreamingResponse
from app.core.exceptions import NotFoundError
from app.core.response import SuccessResponse
from app.security.assets import CanonicalAssetNotFoundError
from app.services.media_service import MediaProcessor, Operation
router = APIRouter(tags=["media"])
def get_processor(request: Request) -> MediaProcessor:
return request.app.state.container.processor
async def execute_operation(request: Request, name: str, operation: Operation) -> SuccessResponse:
request.state.operation = name
processor = get_processor(request)
resolved = await processor.resolver.resolve(request)
return await processor.run(resolved, name, operation)
async def stream_file(path: Path) -> AsyncIterator[bytes]:
async with aiofiles.open(path, "rb") as media:
while chunk := await media.read(1024 * 1024):
yield chunk
@router.get("/v1/media/{request_id}/{filename}", name="download_media")
async def download_media(request: Request, request_id: str, filename: str) -> StreamingResponse:
request.state.operation = "media.download"
container = request.app.state.container
# The filesystem locator is not an authorization token. In authenticated
# deployments an output must have been issued by the pipeline to the
# caller's authoritative workspace before it can be downloaded.
if container.settings.auth_enabled:
context = getattr(request.state, "auth", None)
if context is None or not context.workspace_id:
raise NotFoundError("Output file not found")
try:
asset = await container.assets.get_owned(
workspace_id=context.workspace_id,
request_id=request_id,
filename=filename,
)
path = container.cleanup.resolve_download(request_id, asset.filename)
await container.assets.verify_file(asset, path)
except CanonicalAssetNotFoundError as exc:
raise NotFoundError("Output file not found") from exc
else:
path = container.cleanup.resolve_download(request_id, filename)
media_type = container.validator.infer_mime(path)
headers = {
"Content-Disposition": f'attachment; filename="{path.name}"',
"Content-Length": str(path.stat().st_size),
"X-Request-ID": request_id,
}
return StreamingResponse(stream_file(path), media_type=media_type, headers=headers)