Generación Swagger/OpenAPI para Rust: Utoipa — herramienta moderna para documentación automática
Al desarrollar aplicaciones web en Rust, la documentación de la API no es un lujo, sino una necesidad. La biblioteca Utoipa (abreviatura de "Utopia") proporciona una forma potente y elegante de generar especificaciones OpenAPI directamente desde el código. Se integra con frameworks web populares como actix-web, axum, rocket y warp, y permite describir endpoints, esquemas de datos y parámetros mediante atributos y macros.
Características principales de Utoipa
- Generación automática de OpenAPI 3.0/3.1 — sin necesidad de escribir YAML/JSON manualmente.
- Soporte para múltiples frameworks — actix-web, axum, rocket, warp.
- Integración con Swagger UI — componente integrado para visualizar la documentación.
- Descripción profunda de esquemas — soporte para estructuras anidadas, enumeraciones, campos opcionales.
- Macros para descripción rápida —
#[utoipa::path],#[openapi]. - Validación de especificaciones — verificación de la corrección del documento generado.
Instalación y configuración
Agregue las dependencias en Cargo.toml. Como ejemplo, elegimos el framework actix-web:
[dependencies]utoipa = "4"utoipa-swagger-ui = { version = "4", features = ["actix-web"] }actix-web = "4"serde = { version = "1", features = ["derive"] }Ejemplo básico: creación de una API con documentación
Consideremos un CRUD simple para la entidad "Usuario". Comencemos definiendo el modelo de datos:
use serde::{Deserialize, Serialize};use utoipa::ToSchema;
#[derive(Serialize, Deserialize, ToSchema)]pub struct User { #[schema(example = "1")] pub id: i32, #[schema(example = "john_doe")] pub username: String, #[schema(example = "john@example.com")] pub email: String,}Ahora describimos el endpoint para obtener la lista de usuarios usando la macro #[utoipa::path]:
use actix_web::{get, web, HttpResponse, Responder};use utoipa::OpenApi;
#[utoipa::path( get, path = "/users", responses( (status = 200, description = "Lista de usuarios", body = Vec<User>) ))]#[get("/users")]async fn get_users() -> impl Responder { let users = vec![ User { id: 1, username: "alice".into(), email: "alice@example.com".into() }, User { id: 2, username: "bob".into(), email: "bob@example.com".into() }, ]; HttpResponse::Ok().json(users)}Construcción del documento OpenAPI y Swagger UI
Creamos una estructura para describir toda la API:
#[derive(OpenApi)]#[openapi( paths(get_users), components(schemas(User)))]pub struct ApiDoc;
// En la función main configuramos Swagger UIuse utoipa_swagger_ui::SwaggerUi;
#[actix_web::main]async fn main() -> std::io::Result<()> { use actix_web::App;
HttpServer::new(|| { App::new() .service(get_users) .service( SwaggerUi::new("/swagger-ui/{_:.*}") .url("/api-docs/openapi.json", ApiDoc::openapi()) ) }) .bind("127.0.0.1:8080")? .run() .await}Después de ejecutar la aplicación, la documentación estará disponible en http://localhost:8080/swagger-ui/.
Funcionalidades avanzadas: esquemas anidados y parámetros
Utoipa admite tipos de datos complejos. Por ejemplo, agreguemos un campo con una estructura anidada:
#[derive(Serialize, Deserialize, ToSchema)]pub struct Address { #[schema(example = "Moscú")] pub city: String, #[schema(example = "Calle Lenin, 1")] pub street: String,}
También en la biblioteca
Métricas de Prometheus en Kotlin: integración con Micrometer y Ktor
Configuración de aplicaciones Java: bibliotecas y herramientas
mapstructure en Go: guía completa con ejemplos prácticos