from fastapi import APIRouter, HTTPException, Query, Request from fastapi.responses import StreamingResponse import requests import os from typing import Optional router = APIRouter() # Headers para bypass de restricciones DEFAULT_HEADERS = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 'Accept': '*/*', 'Accept-Language': 'en-US,en;q=0.9', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1' } def stream_content(url: str, headers: dict): """Genera el contenido del stream""" try: with requests.get(url, headers=headers, stream=True, timeout=30) as response: response.raise_for_status() for chunk in response.iter_content(chunk_size=8192): if chunk: yield chunk except requests.RequestException as e: print(f"Error streaming content: {e}") raise HTTPException(status_code=502, detail="Error al obtener el contenido") @router.get("/proxy") async def proxy_stream( request: Request, url: str = Query(..., description="URL del stream a proxificar") ): """Proxy para streams bloqueados por CORS o geolocalización""" if not url: raise HTTPException(status_code=400, detail="URL requerida") try: # Preparar headers proxy_headers = DEFAULT_HEADERS.copy() # Agregar headers del cliente si son relevantes client_headers = dict(request.headers) if 'referer' in client_headers: proxy_headers['Referer'] = client_headers['referer'] # Hacer petición inicial para obtener headers de respuesta head_response = requests.head(url, headers=proxy_headers, timeout=10) # Preparar headers de respuesta response_headers = {} # Copiar headers importantes important_headers = [ 'content-type', 'content-length', 'accept-ranges', 'cache-control', 'expires', 'last-modified' ] for header in important_headers: if header in head_response.headers: response_headers[header] = head_response.headers[header] # Headers CORS response_headers.update({ 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS', 'Access-Control-Allow-Headers': '*' }) # Retornar stream return StreamingResponse( stream_content(url, proxy_headers), headers=response_headers, media_type=head_response.headers.get('content-type', 'application/octet-stream') ) except requests.RequestException as e: print(f"Proxy error for URL {url}: {e}") raise HTTPException(status_code=502, detail="Error al acceder al contenido") except Exception as e: print(f"Unexpected proxy error: {e}") raise HTTPException(status_code=500, detail="Error interno del servidor") @router.options("/proxy") async def proxy_options(): """Maneja peticiones OPTIONS para CORS""" return { "message": "OK" }