¡Bienvenidos de nuevo a Rustaceo.es! En esta guía, haremos un recorrido por todo el proceso de construcción de una API RESTful en Rust, desde el diseño inicial hasta la integración con bases de datos y la implementación de pruebas automatizadas.
Si has seguido nuestras entregas anteriores, ahora consolidaremos todos esos conocimientos en una visión completa de cómo construir una API REST en Rust de manera eficiente y segura.
🚀 Pasos claves en la construcción de una api restful #
- Diseño e Implementación Base con Actix-Web.
- Integración con SQLx para la Persistencia de Datos.
- Pruebas Automatizadas para Asegurar la Calidad.
🏗 1️⃣ Implementación base con actix-web #
La base de cualquier API en Rust comienza con la configuración de un servidor HTTP. Actix-Web es un framework rápido y eficiente que nos permite manejar rutas, peticiones y respuestas con facilidad.
📌 Estructura Base de un Servidor en Actix-Web
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
async fn bienvenida() -> impl Responder {
HttpResponse::Ok().body("¡Bienvenido a la API de Pokémon en Rust!")
}
#[Actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/", web::get().to(bienvenida))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
✔ Manejo de solicitudes HTTP con HttpServer y App. ✔ Definición de rutas con web::route(). ✔ Respuesta básica en JSON.
📦 2️⃣ Persistencia con sqlx y postgresql #
El siguiente paso es agregar una base de datos para almacenar y gestionar datos. Para esto, utilizamos SQLx, una biblioteca asincrónica para trabajar con bases de datos en Rust.
📌 Conexión con PostgreSQL usando SQLx
use sqlx::PgPool;
use actix_web::{web, App, HttpServer};
use dotenv::dotenv;
use std::env;
#[Actix_web::main]
async fn main() -> std::io::Result<()> {
dotenv().ok();
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL no está configurado");
let pool = PgPool::connect(&database_url).await.expect("No se pudo conectar a la BD");
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(pool.clone()))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
✔ Configuración de conexión a PostgreSQL. ✔ Uso de dotenv para manejar variables de entorno. ✔ Reutilización del pool de conexiones con web::Data.
📌 Ejemplo de consulta a la base de datos
async fn listar_elemento(pool: web::Data<PgPool>) -> impl Responder {
let elementoes = sqlx::query!("SELECT id, nombre, tipo FROM elementoes")
.fetch_all(pool.get_ref())
.await;
match elementoes {
Ok(elementoes) => HttpResponse::Ok().json(elementoes),
Err(_) => HttpResponse::InternalServerError().finish(),
}
}
✔ Ejecución de consultas seguras con SQLx. ✔ Manejo de errores para evitar caídas en la API.
🛠 3️⃣ Implementación de tests automatizados #
Para garantizar la calidad de nuestra API, implementamos tests unitarios y de integración utilizando actix-web::test.
📌 Ejemplo de Test para la Ruta de Bienvenida
#[Cfg(test)]
mod tests {
use super::*;
use actix_web::{test, App};
#[actix_web::test]
async fn test_bienvenida() {
let app = test::init_service(App::new().route("/", web::get().to(bienvenida))).await;
let req = test::TestRequest::get().uri("/").to_request();
let resp = test::call_service(&app, req).await;
assert!(resp.status().is_success());
}
}
✔ Pruebas automatizadas para garantizar respuestas correctas. ✔ Uso de test::init_service() para inicializar la API.
📌 Test para la Creación de un Pokémon
#[Actix_web::test]
async fn test_agregar_elemento() {
let pool = establecer_conexion_test().await;
let app = test::init_service(
App::new()
.app_data(web::Data::new(pool.clone()))
.route("/elementoes", web::post().to(agregar_elemento)),
)
.await;
let nuevo_elemento = json!({"nombre": "Item4", "tipo": "Planta"});
let req = test::TestRequest::post()
.uri("/elementoes")
.set_json(&nuevo_elemento)
.to_request();
let resp = test::call_service(&app, req).await;
assert_eq!(resp.status(), 201);
}
✔ Verificación de la creación de un Pokémon en la base de datos. ✔ Uso de test::set_json() para simular una petición POST.
📌 Conclusión #
Hemos consolidado todos los elementos clave de nuestra API RESTful en Rust:
🎯 Resumen de lo aprendido: ✔ Configuración y estructura base con Actix-Web. ✔ Persistencia con PostgreSQL usando SQLx. ✔ Implementación de pruebas automatizadas.
🔮 Próximo paso: Mejorar la API con autenticación, paginación y control de acceso.
¡Nos vemos en la próxima entrega, Rustaceos!