Creación de API RESTful para Blog con Postman y Rust
Clase 14 de 21 • Curso de Backend con Rust: Bases de Datos, Controladores y Templates
Resumen
Siempre será necesario crear nuevos registros en la base de datos y exponer esta posibilidad desde una API para que el usuario pueda crear un nuevo registro desde un cliente.
Generando nuevos registros dinámicamente
Hagamos posible que el usuario envíe información desde un cliente al backend, este los procese y los inserte en la base de datos.
Paso 1. Preparación del modelo
Comienza instalando algunas nuevas dependencias que nos ayudarán a trabajar con datos en formato JSON. Estas son:
[dependencies]
json = "0.12"
serde = { version = "1.0.104", features = ["derive"] }
serde_json = "1.0"
Utilizaremos las mismas en el archivo model.rs
creando estructuras que nos permitan manipular la información de entrada del tipo JSON y convertirla en un registro en la BBDD.
use diesel::prelude::*;
use super::schema::posts;
// Permitimos a las estructuras manipular datos en formato JSON
use serde::{Deserialize, Serialize};
// Estructura para obtener los registros completos desde la BBDD
#[derive(Queryable, Debug, Deserialize, Serialize)]
pub struct Post {
pub id: i32,
pub title: String,
pub slug: String,
pub body: String,
}
// Estructura para obtener solo algunos campos de los registros
#[derive(Queryable, Debug, Deserialize, Serialize)]
pub struct PostSimplificado {
pub title: String,
pub body: String,
}
// Estructura para crear registros en la BBDD con el formato de un post
#[derive(Insertable)]
#[table_name="posts"]
pub struct NewPost<'a> {
pub title: &'a str,
pub body: &'a str,
pub slug: &'a str,
}
// Estrucutra para recibir desde un cliente datos en formato JSON
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct NewPostHandler {
pub title: String,
pub body: String
}
Por otro lado, también vamos a implementar en la estructura Post
algunas funciones que nos ayudarán en que el código fuente sea más prolijo.
impl Post {
// Función para crear un String con el formato de un 'slug', minúscula y separado por guión medio
pub fn slugify(title: &String) -> String {
return title.replace(" ", "-").to_lowercase();
}
// Función para crear un nuevo Post en la BBDD a partir de datos de entrada
pub fn create_post<'a> (
conn: &PgConnection,
post: &NewPostHandler
) -> Result<Post, diesel::result::Error> {
let slug = Post::slugify(&post.title.clone());
let new_post = NewPost{
title: &post.title,
slug: &slug,
body: &post.body
};
diesel::insert_into(posts::table).values(new_post).get_result::<Post>(conn)
}
}
Paso 2. Creación del endpoint
Ahora es momento de crear una nueva función del tipo POST en el archivo main.rs
para recibir datos e insertarlos en la base de datos.
#[post("/new_post")]
async fn new_post(pool: web::Data<DbPool>, item: web::Json<NewPostHandler>) -> impl Responder {
// Traemos el POOL para disponer de la conexión a la BBDD
let conn = pool.get().expect("Problemas al traer la base de datos");
// Utiliamos la función creada en el modelo para crear un nuevo registro y devolverlo
match web::block(move || {Post::create_post(&conn, &item)}).await {
Ok(data) => {
return HttpResponse::Ok().body(format!("{:?}", data));
},
Err(err) => HttpResponse::Ok().body("Error al recibir la data")
}
}
Y no olvides implementar el nuevo endpoint en el servidor HTTP para exponerlo:
HttpServer::new(move || {
App::new()
.service(index)
.service(new_post)
.app_data(web::Data::new(pool.clone()))
}).bind(("127.0.0.1", 8080)).unwrap().run().await
Este nuevo endpoint se consume desde 127.0.0.8080/new_post
con una solicitud del tipo POST. El navegador web no te servirá en esta ocasión, así que tendrás que emplear un cliente HTTP como Postman o Insomnia. La solicitud recibe un Body como el siguiente:
{
"title": "Nuevo post",
"body": "Lorem ipsum!!"
}
De esta manera, generarás un nuevo registro y podrás observarlos desde el endpoint GET 127.0.0.8080/
para corroborar que efectivamente se hayan generado los nuevos posts.
Crea tantos registros como quieras en la base de datos. Hemos logrado abrir un canal de comunicación entre un cliente y un servidor para enviar y guardar datos en una base de datos.
Contribución creada por: Kevin Fiorentino.