¿Qué es Tower y para qué sirve?
\n\nTower 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\nLa 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.
¿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
Instalación de Tower
\n\nTower 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:
[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\nDespués, ejecuta el siguiente comando en la terminal:
\ncargo build\n\nLa librería se descargará y compilará junto con tu proyecto.
\n\nInicio rápido: Tu primer servicio y middleware
\n\nVamos 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\nuse 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 También en la biblioteca
Procesamiento de Markdown en Swift para iOS y macOS: bibliotecas y ejemplos
Tokens JWT en Kotlin: generación, verificación y uso con io.jsonwebtoken
Generación de PDF en Kotlin: bibliotecas y herramientas (iText, Apache PDFBox)
Trabajo con Markdown en Kotlin: bibliotecas, análisis y generación
EasyNetQ para C# (.NET): guía completa con ejemplos prácticos