Introdução: Por que Rust para REST API?
Rust é uma linguagem de programação de sistemas moderna que combina o desempenho de C/C++ com segurança de memória. Nos últimos anos, tem sido ativamente usada para criar serviços web de alta carga e REST APIs. Graças ao framework Actix-web, escrever uma REST API completa em Rust pode levar apenas 30 minutos, mesmo se você está começando a aprender a linguagem.
Neste artigo, criaremos uma REST API simples, mas funcional, para gerenciar uma lista de tarefas (Todo List). Você aprenderá a:
- Configurar um projeto Rust com Actix-web
- Implementar operações CRUD (Create, Read, Update, Delete)
- Trabalhar com requisições e respostas JSON
- Usar roteamento e handlers
Pronto? Vamos lá!
Passo 1: Configuração do projeto e instalação de dependências
Primeiro, certifique-se de que você tem o Rust instalado. Se não, execute o comando:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shCrie um novo projeto:
cargo new rust_todo_apicd rust_todo_apiAbra o arquivo Cargo.toml e adicione as seguintes dependências:
[dependencies]actix-web = "4"serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"tokio = { version = "1", features = ["full"] }Aqui:
- actix-web — um poderoso framework web assíncrono
- serde — para serialização/desserialização JSON
- tokio — runtime assíncrono (Actix-web o usa internamente)
Execute cargo build para baixar e compilar as dependências. Isso levará de 2 a 3 minutos.
Passo 2: Criando o modelo de dados e o armazenamento
Neste projeto, não conectaremos um banco de dados — para simplificar, usaremos um vetor em memória. Vamos criar uma estrutura para a tarefa.
Abra src/main.rs e escreva o seguinte código:
use actix_web::{web, App, HttpServer, HttpResponse, middleware};use serde::{Deserialize, Serialize};use std::sync::Mutex;
// Modelo da tarefa#[derive(Serialize, Deserialize, Clone)]struct Task { id: u32, title: String, completed: bool,}
// Armazenamento de tarefas (thread-safe)struct AppState { tasks: Mutex<Vec<Task>>,}Explicações:
- #[derive(Serialize, Deserialize)] — gera automaticamente métodos para trabalhar com JSON
- Mutex — garante acesso seguro aos dados a partir de múltiplas threads
- AppState — será armazenado no estado da aplicação
Passo 3: Implementação dos handlers CRUD
Agora vamos adicionar funções handler para cada método HTTP. Insira o seguinte código após a declaração das estruturas:
// Obter todas as tarefasasync fn get_tasks(data: web::Data<AppState>) -> HttpResponse { let tasks = data.tasks.lock().unwrap(); HttpResponse::Ok().json(tasks.clone())}
// Criar uma nova tarefaasync fn create_task(data: web::Data<AppState>, body: web::Json<Task>) -> HttpResponse { let mut tasks = data.tasks.lock().unwrap(); let new_id = tasks.len() as u32 + 1; let task = Task { id: new_id, title: body.title.clone(), completed: body.completed, }; tasks.push(task.clone()); HttpResponse::Created().json(task)}
// Atualizar uma tarefaasync fn update_task( data: web::Data<AppState>, path: web::Path<u32>, body: web::Json<Task>,) -> HttpResponse { let mut tasks = data.tasks.lock().unwrap(); let id = path.into_inner(); if let Some(task) = tasks.iter_mut().find(|t| t.id == id) { task.title = body.title.clone(); task.completed = body.completed; HttpRespons