GraphQL API con Rust: tutorial práctico paso a paso

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

API GraphQL con Rust: tutorial práctico paso a paso



GraphQL es un potente lenguaje de consultas para API que permite a los clientes solicitar solo los datos que necesitan. Combinado con el rendimiento y la seguridad de Rust, obtienes una solución ideal para servicios web de alta carga. En este tutorial crearemos una API GraphQL completa desde cero, utilizando el crate async-graphql.



¿Por qué Rust? Proporciona abstracciones de costo cero, seguridad de memoria y una velocidad impresionante. GraphQL en Rust funciona más rápido que sus equivalentes en JavaScript o Python, lo cual es crítico para sistemas en producción.



1. Configuración del proyecto y dependencias



Empecemos creando un nuevo proyecto Rust. Abre la terminal y ejecuta:



cargo new graphql_rust_apicd graphql_rust_api


Ahora agreguemos las dependencias necesarias en el archivo Cargo.toml:



[dependencies]async-graphql = "7.0"async-graphql-actix-web = "7.0"actix-web = "4"actix-cors = "0.7"serde = { version = "1.0", features = ["derive"] }tokio = { version = "1", features = ["full"] }


Estos crates proporcionan todo lo necesario: async-graphql — el núcleo de GraphQL, actix-web — el servidor web, serde — la serialización de datos.



2. Creación del modelo de datos y esquema



Definamos un modelo simple para nuestra API — libros. Crearemos las estructuras y el esquema GraphQL:



use async_graphql::*;use serde::{Serialize, Deserialize};

#[derive(Clone, Debug, Serialize, Deserialize, SimpleObject)]struct Book { id: ID, title: String, author: String, year: i32,}

#[derive(Clone, Debug, Serialize, Deserialize, InputObject)]struct BookInput { title: String, author: String, year: i32,}


Observa los atributos #[derive(SimpleObject)] y #[derive(InputObject)]. El primero genera automáticamente un tipo GraphQL para salida, el segundo para entrada de datos.



3. Implementación de resolvers (Query y Mutation)



Los resolvers son funciones que procesan las consultas. Crearemos una estructura de almacenamiento y los resolvers:



use std::sync::Mutex;

struct QueryRoot;

#[Object]impl QueryRoot { async fn books(&self, ctx: &Context<'_>) -> Vec<Book> { let storage = ctx.data_unchecked::<Mutex<Vec<Book>>>(); storage.lock().unwrap().clone() }

async fn book(&self, ctx: &Context<'_>, id: ID) -> Option<Book> { let storage = ctx.data_unchecked::<Mutex<Vec<Book>>>(); storage.lock().unwrap().iter().find(|b| b.id == id).cloned() }}

struct MutationRoot;

#[Object]impl MutationRoot { async fn add_book(&self, ctx: &Context<'_>, input: BookInput) -> Book { let mut storage = ctx.data_unchecked::<Mutex<Vec<Book>>>() .lock().unwrap(); let book = Book { id: ID::from(storage.len() + 1), title: input.title, author: input.author, year: input.year, }; storage.push(book.clone()); book }}


Usamos Mutex para acceso seguro a los datos en entornos concurrentes. En un proyecto real conectarías una base de datos, pero para este tutorial es la opción ideal.



4. Compilación e inicio del servidor



El paso final es unir todo en un servidor funcional. Crearemos el punto de entrada:



use actix_web::{guard, web, App, HttpServer, HttpRequest, HttpResponse};use actix_cors::Cors;use async_graphql_actix_web::{GraphQLRequest, GraphQLResponse};

async fn index( schema: web::Data<Schema<QueryRoot, MutationRoot, EmptySubscription>>, req: GraphQLRequest,) -> GraphQLResponse { schema.execute(req.into_inner()).await.into()}

#[actix_web::main]async fn main() -> std::

Blogs

Book Recommendations