Files
MoviePilot/app/api/presentation/sse.py
T

46 lines
1.3 KiB
Python

"""SSE wire mapping and response lifecycle helpers."""
import json
from collections.abc import AsyncIterable, Iterable
from typing import Any
from fastapi.responses import StreamingResponse
SSE_HEADERS = {
"Cache-Control": "no-cache, no-transform",
"Connection": "keep-alive",
"X-Accel-Buffering": "no",
}
def encode_data_event(payload: dict[str, Any]) -> str:
"""Encode an OpenAI-style unnamed SSE data event."""
return f"data: {json.dumps(payload, ensure_ascii=False)}\n\n"
def encode_named_event(event: str, payload: dict[str, Any]) -> str:
"""Encode a named SSE event without applying a response envelope."""
return (
f"event: {event}\n"
f"data: {json.dumps(payload, ensure_ascii=False)}\n\n"
)
def build_sse_response(
content: AsyncIterable[str] | Iterable[str],
*,
headers: dict[str, str] | None = None,
) -> StreamingResponse:
"""Build a non-buffered SSE response and merge protocol-specific headers."""
return StreamingResponse(
content,
media_type="text/event-stream",
headers={**SSE_HEADERS, **(headers or {})},
)
def build_sse_error_response(payload: str) -> StreamingResponse:
"""Build a one-event SSE error response using the common transport policy."""
return build_sse_response(iter([payload]))