Tower para Rust: guía completa con ejemplos

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿Qué es Tower y para qué sirve?

\n\n

Tower es una librería fundamental del ecosistema de Rust que proporciona abstracciones para construir servicios de red modulares, componibles y asíncronos, así como middleware. No es un framework HTTP listo para usar (como Actix-web o Axum), sino más bien un "material de construcción" para ellos. Axum, por ejemplo, está construido sobre Tower.

\n\n

La idea principal de Tower es el trait Service, que representa una función asíncrona que transforma una solicitud (Request) en una respuesta (Response). El middleware (o "Layer") en Tower es una forma de envolver un servicio con otro, añadiendo comportamiento adicional (logging, autenticación, timeouts, balanceo de carga, etc.) sin modificar el código original del servicio.

\n\n

¿Para qué sirve?

\n
    \n
  • Modularidad: Puedes dividir la lógica compleja de procesamiento de solicitudes en componentes pequeños, independientes y reutilizables (servicios y middleware).
  • \n
  • Capacidad de composición: El middleware se puede combinar fácilmente, "superponiéndolos" unos sobre otros como capas (layers).
  • \n
  • Asincronía: Tower está diseñada para funcionar con Rust asíncrono (tokio, async-std) y soporta futures.
  • \n
  • Capacidad de prueba: Cada componente se puede probar de forma aislada.
  • \n
\n\n

Instalación de Tower

\n\n

Tower es una librería de Rust, por lo que se instala a través del gestor de paquetes Cargo. Añade la dependencia a tu archivo Cargo.toml:

\n\n
[dependencies]\ntower = { version = "0.4", features = ["full"] } # "full" incluye todas las características\ntokio = { version = "1", features = ["full"] } # Para el runtime asíncrono\n
\n\n

Después, ejecuta el siguiente comando en la terminal:

\n
cargo build
\n\n

La librería se descargará y compilará junto con tu proyecto.

\n\n

Inicio rápido: Tu primer servicio y middleware

\n\n

Vamos a crear un servicio simple que recibe una cadena y la devuelve en mayúsculas. Luego lo envolveremos en un middleware que registra cada solicitud.

\n\n
use std::convert::Infallible;\nuse std::task::{Context, Poll};\nuse tower::{Service, Layer, ServiceBuilder};\nuse tower::layer::util::Identity;\nuse std::future::{Ready, ready};\n\n// 1. Definimos nuestro servicio\n#[derive(Clone)]\nstruct MyService;\n\nimpl<Request> Service<Request> for MyService {\n    type Response = String;\n    type Error = Infallible;\n    type Future = Ready<Result<Self::Response, Self::Error>>;\n\n    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n        Poll::Ready(Ok(()))\n    }\n\n    fn call(&mut self, req: Request) -> Self::Future {\n        // Simplemente devolvemos una cadena\n        ready(Ok(format!("¡Hola desde el servicio! Solicitud: {:?}", std::any::type_name::<Request>())))\n    }\n}\n\n// 2. Definimos el middleware para logging\n#[derive(Clone)]\nstruct LogMiddleware;\n\nimpl<S> Layer<S> for LogMiddleware {\n    type Service = LogService<S>;\n\n    fn layer(&self, inner: S) -> Self::Service {\n        LogService { inner }\n    }\n}\n\n#[derive(Clone)]\nstruct LogService<S> {\n    inner: S,\n}\n\nimpl<S, Request> Service<Request> for LogService<S>\nwhere\n    S: Service<Request>,\n    S::Future: std::marker::Send,\n    Request: std::fmt::Debug,\n{\n    type Response = S::Response;\n    type Error = S::Error;\n    type Future = S::Future;\n\n    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n        self.inner.poll_ready(cx)\n    }\n\n    fn call(&mut self, req: Request) -> Self::Future {\n        printl                    

Recommendations