from typing import Annotated from fastapi import Request, Depends, APIRouter, Query, HTTPException from .handlers import handle_hls_stream_proxy, proxy_stream, get_manifest, get_playlist, get_segment, get_public_ip from .schemas import MPDSegmentParams, MPDPlaylistParams, HLSManifestParams, ProxyStreamParams, MPDManifestParams from .utils.http_utils import get_proxy_headers, ProxyRequestHeaders proxy_router = APIRouter() @proxy_router.head("/hls/manifest.m3u8") @proxy_router.get("/hls/manifest.m3u8") async def hls_stream_proxy( request: Request, hls_params: Annotated[HLSManifestParams, Query()], proxy_headers: Annotated[ProxyRequestHeaders, Depends(get_proxy_headers)], ): """ Proxify HLS stream requests, fetching and processing the m3u8 playlist or streaming the content. Args: request (Request): The incoming HTTP request. hls_params (HLSPlaylistParams): The parameters for the HLS stream request. proxy_headers (ProxyRequestHeaders): The headers to include in the request. Returns: Response: The HTTP response with the processed m3u8 playlist or streamed content. """ return await handle_hls_stream_proxy(request, hls_params, proxy_headers) @proxy_router.head("/stream") @proxy_router.get("/stream") async def proxy_stream_endpoint( request: Request, stream_params: Annotated[ProxyStreamParams, Query()], proxy_headers: Annotated[ProxyRequestHeaders, Depends(get_proxy_headers)], ): """ Proxies stream requests to the given video URL. Args: request (Request): The incoming HTTP request. stream_params (ProxyStreamParams): The parameters for the stream request. proxy_headers (ProxyRequestHeaders): The headers to include in the request. Returns: Response: The HTTP response with the streamed content. """ content_range = proxy_headers.request.get("range", "bytes=0-") if "nan" in content_range.casefold(): # Handle invalid range requests "bytes=NaN-NaN" raise HTTPException(status_code=416, detail="Invalid Range Header") proxy_headers.request.update({"range": content_range}) return await proxy_stream(request.method, stream_params, proxy_headers) @proxy_router.get("/mpd/manifest.m3u8") async def manifest_endpoint( request: Request, manifest_params: Annotated[MPDManifestParams, Query()], proxy_headers: Annotated[ProxyRequestHeaders, Depends(get_proxy_headers)], ): """ Retrieves and processes the MPD manifest, converting it to an HLS manifest. Args: request (Request): The incoming HTTP request. manifest_params (MPDManifestParams): The parameters for the manifest request. proxy_headers (ProxyRequestHeaders): The headers to include in the request. Returns: Response: The HTTP response with the HLS manifest. """ return await get_manifest(request, manifest_params, proxy_headers) @proxy_router.get("/mpd/playlist.m3u8") async def playlist_endpoint( request: Request, playlist_params: Annotated[MPDPlaylistParams, Query()], proxy_headers: Annotated[ProxyRequestHeaders, Depends(get_proxy_headers)], ): """ Retrieves and processes the MPD manifest, converting it to an HLS playlist for a specific profile. Args: request (Request): The incoming HTTP request. playlist_params (MPDPlaylistParams): The parameters for the playlist request. proxy_headers (ProxyRequestHeaders): The headers to include in the request. Returns: Response: The HTTP response with the HLS playlist. """ return await get_playlist(request, playlist_params, proxy_headers) @proxy_router.get("/mpd/segment.mp4") async def segment_endpoint( segment_params: Annotated[MPDSegmentParams, Query()], proxy_headers: Annotated[ProxyRequestHeaders, Depends(get_proxy_headers)], ): """ Retrieves and processes a media segment, decrypting it if necessary. Args: segment_params (MPDSegmentParams): The parameters for the segment request. proxy_headers (ProxyRequestHeaders): The headers to include in the request. Returns: Response: The HTTP response with the processed segment. """ return await get_segment(segment_params, proxy_headers) @proxy_router.get("/ip") async def get_mediaflow_proxy_public_ip( use_request_proxy: bool = True, ): """ Retrieves the public IP address of the MediaFlow proxy server. Returns: Response: The HTTP response with the public IP address in the form of a JSON object. {"ip": "xxx.xxx.xxx.xxx"} """ return await get_public_ip(use_request_proxy)