Saltar a contenido

Manejo de Errores

Mejores prácticas para manejar errores al usar la API de SubX.

Códigos de Estado HTTP

Código Significado Acción
200 Éxito Procesar la respuesta
400 Solicitud Incorrecta Verificar los parámetros de tu solicitud
401 No Autorizado Verificar tu clave de API
404 No Encontrado El recurso no existe
429 Límite de Tasa Alcanzado Esperar Retry-After segundos y reintentar
500 Error del Servidor Reintentar con retroceso
502 Gateway Incorrecto Fuente no disponible, reintentar más tarde

Formato de Respuesta de Error

Todas las respuestas de error siguen este formato:

{
  "detail": "Mensaje de error describiendo qué salió mal"
}

Para errores de validación (400), la respuesta puede incluir información detallada del campo:

{
  "detail": [
    {
      "loc": ["query", "year"],
      "msg": "ensure this value is greater than or equal to 1900",
      "type": "value_error"
    }
  ]
}

Manejo de Errores en Python

import requests
import time

def search_with_error_handling(api_key, params, max_retries=3):
    """Buscar con manejo integral de errores."""
    headers = {"Authorization": f"Bearer {api_key}"}
    url = "https://subx-api.duckdns.org/api/subtitles/search"

    for attempt in range(max_retries):
        try:
            response = requests.get(url, headers=headers, params=params, timeout=10)

            # Manejar códigos de estado específicos
            if response.status_code == 200:
                return response.json()

            elif response.status_code == 400:
                print(f"Solicitud Incorrecta: {response.json()['detail']}")
                return None  # No reintentar

            elif response.status_code == 401:
                print("No Autorizado: Verifica tu clave de API")
                return None  # No reintentar

            elif response.status_code == 404:
                print("No Encontrado: El recurso no existe")
                return None  # No reintentar

            elif response.status_code == 429:
                # Límite de tasa - usar header Retry-After
                retry_after = int(response.headers.get("Retry-After", 60 * (attempt + 1)))
                print(f"Límite de tasa alcanzado. Esperando {retry_after}s...")
                time.sleep(retry_after)
                continue

            elif response.status_code >= 500:
                # Error del servidor - reintentar
                if attempt < max_retries - 1:
                    wait_time = 60 * (attempt + 1)
                    print(f"Error del servidor. Reintentando en {wait_time}s...")
                    time.sleep(wait_time)
                    continue
                else:
                    print("Error del servidor persiste después de reintentos")
                    return None

        except requests.exceptions.Timeout:
            print(f"Tiempo de espera agotado (intento {attempt + 1}/{max_retries})")
            if attempt < max_retries - 1:
                time.sleep(60 * (attempt + 1))
                continue

        except requests.exceptions.ConnectionError:
            print(f"Error de conexión (intento {attempt + 1}/{max_retries})")
            if attempt < max_retries - 1:
                time.sleep(60 * (attempt + 1))
                continue

        except Exception as e:
            print(f"Error inesperado: {e}")
            return None

    return None

Validación Antes de Solicitudes

Validar parámetros antes de hacer solicitudes:

def validate_search_params(params):
    """Validar parámetros de búsqueda antes de hacer la solicitud."""
    errors = []

    # Se requiere al menos un criterio de búsqueda
    if not any([params.get(k) for k in ['query', 'title', 'imdb_id', 'public_id']]):
        errors.append("Se requiere al menos un criterio de búsqueda")

    # Validación de año
    if 'year' in params:
        year = params['year']
        if not (1900 <= year <= 2100):
            errors.append(f"El año debe estar entre 1900 y 2100, se obtuvo {year}")

    # Validación de límite
    if 'limit' in params:
        limit = params['limit']
        if not (1 <= limit <= 200):
            errors.append(f"El límite debe estar entre 1 y 200, se obtuvo {limit}")

    if errors:
        raise ValueError(f"Parámetros inválidos: {', '.join(errors)}")

    return True

Configuración de Timeouts

Siempre establecer timeouts para prevenir solicitudes colgadas:

# Timeout corto para verificaciones de salud
response = requests.get("https://subx-api.duckdns.org/api/health", timeout=5)

# Timeout estándar para solicitudes a la API
response = requests.get("https://subx-api.duckdns.org/api/subtitles/search",
                        headers=headers, params=params, timeout=10)

# Timeout más largo para descargas
response = requests.get(f"https://subx-api.duckdns.org/api/subtitles/{id}/download",
                        headers=headers, timeout=60)

Próximos Pasos