HTTP async en FastAPI

Intermedio
FastAPI
FastAPI
Actualizado: 01/07/2025

¡Desbloquea el curso completo!

IA
Ejercicios
Certificado
Entrar

Hacer requests HTTP asíncronos con httpx

En el desarrollo de APIs modernas, es común necesitar comunicarse con servicios externos durante el procesamiento de una petición. Cuando tu aplicación FastAPI necesita obtener datos de otra API, enviar notificaciones o consultar servicios de terceros, realizar estas operaciones de forma asíncrona es fundamental para mantener el rendimiento.

¿Te está gustando esta lección?

Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.

Progreso guardado
Asistente IA
Ejercicios
Iniciar sesión gratis

Más de 25.000 desarrolladores ya confían en CertiDevs

httpx es la biblioteca estándar para realizar peticiones HTTP asíncronas en Python. Funciona como el equivalente asíncrono de la popular biblioteca requests, pero está diseñada específicamente para trabajar con async/await.

Instalación y configuración básica

Para comenzar a usar httpx en tu proyecto FastAPI, primero debes instalarlo:

pip install httpx

La diferencia principal con requests es que httpx permite crear clientes asíncronos que no bloquean el hilo de ejecución mientras esperan la respuesta del servidor remoto:

import httpx
from fastapi import FastAPI

app = FastAPI()

@app.get("/usuarios/{user_id}")
async def obtener_usuario_externo(user_id: int):
    async with httpx.AsyncClient() as client:
        response = await client.get(f"https://jsonplaceholder.typicode.com/users/{user_id}")
        return response.json()

El patrón async with garantiza que el cliente se cierre correctamente después de usar, liberando los recursos de red de manera eficiente.

Métodos HTTP básicos

httpx soporta todos los métodos HTTP estándar con la misma sintaxis familiar de requests, pero en versión asíncrona:

@app.post("/crear-post")
async def crear_post_externo(titulo: str, contenido: str):
    async with httpx.AsyncClient() as client:
        # POST con datos JSON
        post_data = {
            "title": titulo,
            "body": contenido,
            "userId": 1
        }
        response = await client.post(
            "https://jsonplaceholder.typicode.com/posts",
            json=post_data
        )
        return response.json()

@app.put("/actualizar-post/{post_id}")
async def actualizar_post(post_id: int, titulo: str):
    async with httpx.AsyncClient() as client:
        # PUT para actualizar
        response = await client.put(
            f"https://jsonplaceholder.typicode.com/posts/{post_id}",
            json={"title": titulo}
        )
        return response.json()

@app.delete("/eliminar-post/{post_id}")
async def eliminar_post(post_id: int):
    async with httpx.AsyncClient() as client:
        # DELETE
        response = await client.delete(
            f"https://jsonplaceholder.typicode.com/posts/{post_id}"
        )
        return {"eliminado": response.status_code == 200}

Manejo de headers y autenticación

Las APIs externas frecuentemente requieren headers específicos o tokens de autenticación. httpx facilita el envío de esta información:

@app.get("/datos-protegidos")
async def obtener_datos_protegidos():
    headers = {
        "Authorization": "Bearer tu-token-aqui",
        "Content-Type": "application/json",
        "User-Agent": "MiApp/1.0"
    }
    
    async with httpx.AsyncClient() as client:
        response = await client.get(
            "https://api.ejemplo.com/datos",
            headers=headers
        )
        return response.json()

Para autenticación básica, httpx proporciona un método conveniente:

@app.get("/api-con-auth-basica")
async def consultar_api_con_auth():
    async with httpx.AsyncClient() as client:
        response = await client.get(
            "https://api.ejemplo.com/datos",
            auth=("usuario", "contraseña")
        )
        return response.json()

Combinando múltiples peticiones

Una ventaja significativa de la programación asíncrona es la capacidad de realizar múltiples peticiones HTTP simultáneamente sin bloquear la aplicación:

import asyncio

@app.get("/resumen-usuario/{user_id}")
async def obtener_resumen_usuario(user_id: int):
    async with httpx.AsyncClient() as client:
        # Realizar múltiples peticiones en paralelo
        usuario_task = client.get(f"https://jsonplaceholder.typicode.com/users/{user_id}")
        posts_task = client.get(f"https://jsonplaceholder.typicode.com/users/{user_id}/posts")
        albums_task = client.get(f"https://jsonplaceholder.typicode.com/users/{user_id}/albums")
        
        # Esperar a que todas las peticiones terminen
        usuario_response, posts_response, albums_response = await asyncio.gather(
            usuario_task, posts_task, albums_task
        )
        
        return {
            "usuario": usuario_response.json(),
            "posts": posts_response.json(),
            "albums": albums_response.json()
        }

Cliente reutilizable

Para aplicaciones que realizan múltiples peticiones a la misma API, es más eficiente crear un cliente reutilizable que mantenga las conexiones abiertas:

# Cliente global para reutilizar conexiones
http_client = httpx.AsyncClient(
    base_url="https://jsonplaceholder.typicode.com",
    headers={"User-Agent": "MiApp/1.0"}
)

@app.get("/posts")
async def listar_posts():
    response = await http_client.get("/posts")
    return response.json()

@app.get("/posts/{post_id}")
async def obtener_post(post_id: int):
    response = await http_client.get(f"/posts/{post_id}")
    return response.json()

# Importante: cerrar el cliente al finalizar la aplicación
@app.on_event("shutdown")
async def cerrar_cliente():
    await http_client.aclose()

Manejo básico de errores

Es fundamental manejar los errores que pueden ocurrir durante las peticiones HTTP, como problemas de conectividad o respuestas de error del servidor:

from fastapi import HTTPException

@app.get("/usuario-seguro/{user_id}")
async def obtener_usuario_con_manejo_errores(user_id: int):
    try:
        async with httpx.AsyncClient() as client:
            response = await client.get(
                f"https://jsonplaceholder.typicode.com/users/{user_id}"
            )
            
            # Verificar si la petición fue exitosa
            if response.status_code == 404:
                raise HTTPException(status_code=404, detail="Usuario no encontrado")
            
            response.raise_for_status()  # Lanza excepción si hay error HTTP
            return response.json()
            
    except httpx.RequestError:
        # Error de conectividad
        raise HTTPException(status_code=503, detail="Servicio externo no disponible")
    except httpx.HTTPStatusError:
        # Error HTTP (4xx, 5xx)
        raise HTTPException(status_code=502, detail="Error en servicio externo")

Esta aproximación te permite integrar servicios externos en tus endpoints FastAPI manteniendo la naturaleza asíncrona de tu aplicación, lo que resulta en mejor rendimiento y capacidad de respuesta para tus usuarios.

Aprendizajes de esta lección

  • Comprender la importancia de realizar peticiones HTTP asíncronas en FastAPI.
  • Aprender a usar httpx para crear clientes asíncronos y realizar solicitudes HTTP.
  • Conocer cómo manejar headers y autenticación en peticiones externas.
  • Implementar múltiples peticiones concurrentes para optimizar el rendimiento.
  • Aplicar técnicas básicas de manejo de errores en peticiones HTTP asíncronas.

Completa FastAPI y certifícate

Únete a nuestra plataforma y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.

Asistente IA

Resuelve dudas al instante

Ejercicios

Practica con proyectos reales

Certificados

Valida tus conocimientos

Más de 25.000 desarrolladores ya se han certificado con CertiDevs

⭐⭐⭐⭐⭐
4.9/5 valoración