File size: 3,282 Bytes
84121fd |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
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"
} |