|
from fastapi import APIRouter, HTTPException, Query, Request |
|
from fastapi.responses import StreamingResponse |
|
import requests |
|
import os |
|
from typing import Optional |
|
|
|
router = APIRouter() |
|
|
|
|
|
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: |
|
|
|
proxy_headers = DEFAULT_HEADERS.copy() |
|
|
|
|
|
client_headers = dict(request.headers) |
|
if 'referer' in client_headers: |
|
proxy_headers['Referer'] = client_headers['referer'] |
|
|
|
|
|
head_response = requests.head(url, headers=proxy_headers, timeout=10) |
|
|
|
|
|
response_headers = {} |
|
|
|
|
|
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] |
|
|
|
|
|
response_headers.update({ |
|
'Access-Control-Allow-Origin': '*', |
|
'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS', |
|
'Access-Control-Allow-Headers': '*' |
|
}) |
|
|
|
|
|
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" |
|
} |