Rust API com Actix: Como construir seu primeiro CRUD completo
Rust API com Actix é uma combinação perfeita para quem quer performance, segurança e, claro, aquele gostinho de modernidade no desenvolvimento backend. Neste artigo, vou mostrar como montar um CRUD completo usando o Actix Web, sem enrolação e com muita prática. Ah, e se você ainda acha que Rust é só pra sistemas de baixo nível, se prepara pra mudar de ideia.
Por que escolher Actix Web?
Se você já programou backend com Node.js ou Python e ficou meio traumatizado com consumo de memória ou problemas de concorrência, Rust pode ser sua luz no fim do túnel. E com Actix Web, criar APIs é quase como usar magia negra (no bom sentido).
Actix Web é um framework rápido, seguro e fácil de usar. Quer dizer, fácil pra quem já passou pelo básico do Rust. Se não, recomendo assistir a uns tutoriais mais “mamão com açúcar” antes de meter a cara aqui.
Preparando o ambiente para seu CRUD
Antes de tudo, você vai precisar de:
- Rust instalado na sua máquina. Se ainda não tem, é só rodar:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
- Cargo, que já vem junto com o Rust.
- Um editor de texto decente. Recomendo VS Code com extensão pra Rust.
- PostgreSQL ou outro banco de dados que você prefira usar.
Com isso na mão, bora criar o projeto:
cargo new minha_api
cd minha_api
Agora que temos o projeto criado, é hora de adicionar as dependências no Cargo.toml
:
[dependencies]
actix-web = "4"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
sqlx = { version = "0.6", features = ["runtime-actix-native-tls", "postgres"] }
dotenv = "0.15"
bcrypt = "0.10"
Instalou tudo? Então bora pro código.
- Melhor Linguagem de Programação 2025: Explorando as Opções para sua Carreira em Tecnologia
- Hidratação no Front-End: O que é e como ela resolve problemas de SSR e CSR
- Como Sair de Pleno para Senior em 2025: O Guia Definitivo Sem Ficar Batendo Cabeça
- Guia Definitivo: Como e Quando Usar find e findIndex no JavaScript
- Diferença entre every e some no JavaScript: O Guia Definitivo para Quem Já Quebrou a Cabeça com Arrays
- Testes Unitários no Angular: Chega de Código Porco
Configurando o projeto
Preparando o arquivo .env
Antes de conectar com o banco, crie um arquivo .env
na raiz do projeto com as variáveis de ambiente:
DATABASE_URL=postgres://user:password@localhost/minha_api_db
Troque user
, password
e minha_api_db
pelos dados do seu PostgreSQL. Com isso feito, carregue o .env
no projeto. Altere o arquivo main.rs
:
use actix_web::{App, HttpServer};
use dotenv::dotenv;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
dotenv().ok();
HttpServer::new(|| {
App::new()
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
Rodou sem erro? Parabéns, o Actix Web já tá rodando na porta 8080.
Montando o CRUD
Estruturando o projeto
Vamos organizar as coisas. Crie as seguintes pastas e arquivos:
mkdir src/database src/services
touch src/database/mod.rs src/database/connection.rs
touch src/services/mod.rs src/services/user.rs
Configuração de conexão
No arquivo src/database/connection.rs
, configure a conexão com o PostgreSQL:
use sqlx::{PgPool, postgres::PgPoolOptions};
use std::env;
pub async fn connect() -> PgPool {
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL não configurada no .env");
PgPoolOptions::new()
.max_connections(5)
.connect(&database_url)
.await
.expect("Falha ao conectar ao banco de dados")
}
Agora importe isso no src/database/mod.rs
:
pub mod connection;
Criando o banco e as migrations
Para não fazer tudo manualmente, use o SQLx para rodar migrations. Primeiro, instale a CLI do SQLx:
cargo install sqlx-cli --no-default-features --features postgres
Depois, crie a primeira migration:
sqlx migrate add create_users_table
No arquivo criado em migrations
, adicione:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE,
password TEXT NOT NULL
);
Rode as migrations:
sqlx migrate run
Para saber mais sobre o uso de SQLx, confira a documentação oficial.
Criando os modelos
No src/services/user.rs
, adicione:
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct User {
pub id: i32,
pub name: String,
pub email: String,
pub password: String,
}
#[derive(Deserialize)]
pub struct NewUser {
pub name: String,
pub email: String,
pub password: String,
}
#[derive(Deserialize)]
pub struct UpdateUser {
pub name: Option<String>,
pub email: Option<String>,
pub password: Option<String>,
}
Configuração das rotas
No mesmo arquivo, configure as rotas para CRUD:
use actix_web::{web, HttpResponse, Responder};
use crate::database::connection;
use bcrypt::{hash, verify};
pub async fn get_users(pool: web::Data<connection::PgPool>) -> impl Responder {
let users = sqlx::query_as!(User, "SELECT * FROM users")
.fetch_all(pool.get_ref())
.await
.unwrap();
HttpResponse::Ok().json(users)
}
pub async fn create_user(
pool: web::Data<connection::PgPool>,
new_user: web::Json<NewUser>,
) -> impl Responder {
let hashed_password = hash(&new_user.password, 4).unwrap();
sqlx::query!(
"INSERT INTO users (name, email, password) VALUES ($1, $2, $3)",
new_user.name,
new_user.email,
hashed_password
)
.execute(pool.get_ref())
.await
.unwrap();
HttpResponse::Created().finish()
}
pub async fn update_user(
pool: web::Data<connection::PgPool>,
user_id: web::Path<i32>,
updated_user: web::Json<UpdateUser>,
) -> impl Responder {
if let Some(name) = &updated_user.name {
sqlx::query!(
"UPDATE users SET name = $1 WHERE id = $2",
name,
*user_id
)
.execute(pool.get_ref())
.await
.unwrap();
}
if let Some(email) = &updated_user.email {
sqlx::query!(
"UPDATE users SET email = $1 WHERE id = $2",
email,
*user_id
)
.execute(pool.get_ref())
.await
.unwrap();
}
if let Some(password) = &updated_user.password {
let hashed_password = hash(password, 4).unwrap();
sqlx::query!(
"UPDATE users SET password = $1 WHERE id = $2",
hashed_password,
*user_id
)
.execute(pool.get_ref())
.await
.unwrap();
}
HttpResponse::Ok().finish()
}
pub async fn delete_user(
pool: web::Data<connection::PgPool>,
user_id: web::Path<i32>,
) -> impl Responder {
sqlx::query!("DELETE FROM users WHERE id = $1", *user_id)
.execute(pool.get_ref())
.await
.unwrap();
HttpResponse::NoContent().finish()
}
No src/services/mod.rs
, importe:
pub mod user;
E no main.rs
, conecte as rotas:
mod database;
mod services;
use actix_web::web;
use services::user;
use database::connection;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
dotenv().ok();
let pool = connection::connect().await;
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(pool.clone()))
.service(
web::scope("/users")
.route("", web::get().to(user::get_users))
.route("", web::post().to(user::create_user))
.route("/{id}", web::put().to(user::update_user))
.route("/{id}", web::delete().to(user::delete_user))
)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
Testando o CRUD completo
Inicie o servidor:
cargo run
No Postman ou Thunder Client, teste as rotas:
- GET /users: Lista todos os usuários.
- POST /users: Cria um novo usuário com
name
,email
epassword
no corpo da requisição. - PUT /users/{id}: Atualiza os dados de um usuário com base no ID.
- DELETE /users/{id}: Apaga um usuário pelo ID.
Conclusão
Rust API com Actix é uma escolha poderosa pra quem quer desempenho e segurança. Apesar da curva de aprendizado, vale muito a pena. Para mais dicas sobre Rust, confira a documentação oficial do Actix.
Se prepara pra impressionar nas entrevistas ou simplesmente pra dizer adeus às dores de cabeça com bugs de concorrência. E lembra: na próxima vez que alguém falar que Rust é difícil, manda esse artigo de presente!
Angular performance Angular Signals Apps Multiplataforma automação de tarefas Backend Boas Práticas boas práticas Git controle de versão desenvolvedores desenvolvimento backend Desenvolvimento de Software Desenvolvimento Frontend Desenvolvimento Mobile Desenvolvimento Web desenvolvimento ágil devops dicas para devs escalabilidade ferramentas de Git ferramentas de programação Front-end Git Hooks integração contínua inteligência artificial JavaScript Linguagens de Programação Media Queries mercado de tecnologia Mercado de Trabalho Tech Node.js produtividade dev Programação Programação Orientada a Objetos programação para iniciantes programação reativa Python React React Suspense Rust Tecnologia Trunk-Based Development web development workflow Git workflows Git
Publicar comentário