Actix Web | Packages | Rust
- Actix Web | Packages | Rust
Actix Web (Rust)



1. Visão Geral
Actix Web é um framework web de alta performance para Rust, construído sobre o runtime assíncrono do ecossistema Rust (baseado em tokio). É amplamente utilizado para:
- APIs REST de alta concorrência
- Microsserviços
- Gateways HTTP
- Backends com baixa latência
Características técnicas relevantes:
- Modelo actor-based (derivado do ecossistema Actix)
- Execução assíncrona (async/await)
- Alto throughput (comparável a frameworks como FastAPI e Express, porém com footprint menor)
- Forte tipagem em handlers e middlewares
- Sistema robusto de extração de dados (
extractors)
2. Estrutura Básica de Projeto
Criação
cargo new actix_api
cd actix_api
Cargo.toml
[dependencies]
actix-web = "4"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
env_logger = "0.11"
3. Servidor HTTP Mínimo
use actix_web::{get, App, HttpServer, Responder};
#[get("/")]
async fn index() -> impl Responder {
"API online"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(index)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
Conceitos importantes
#[get("/")]: macro para registrar rotaResponder: trait que converte retorno emHttpResponseHttpServer::new: cria pool de workers (por padrão = número de CPUs).run().await: inicia runtime async
4. API REST Realista (CRUD)
Modelo
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone)]
struct User {
id: u32,
name: String,
}
Estado Compartilhado (App State)
use std::sync::Mutex;
struct AppState {
users: Mutex<Vec<User>>,
}
CREATE (POST)
use actix_web::{post, web, HttpResponse};
#[post("/users")]
async fn create_user(
data: web::Data<AppState>,
payload: web::Json<User>,
) -> HttpResponse {
let mut users = data.users.lock().unwrap();
users.push(payload.into_inner());
HttpResponse::Created().finish()
}
READ (GET ALL)
use actix_web::{get, web, HttpResponse};
#[get("/users")]
async fn list_users(data: web::Data<AppState>) -> HttpResponse {
let users = data.users.lock().unwrap();
HttpResponse::Ok().json(users.clone())
}
READ (GET BY ID)
#[get("/users/{id}")]
async fn get_user(
data: web::Data<AppState>,
path: web::Path<u32>,
) -> HttpResponse {
let users = data.users.lock().unwrap();
let id = path.into_inner();
if let Some(user) = users.iter().find(|u| u.id == id) {
HttpResponse::Ok().json(user)
} else {
HttpResponse::NotFound().finish()
}
}
Configuração Completa
use actix_web::{App, HttpServer, web};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let state = web::Data::new(AppState {
users: Mutex::new(vec![]),
});
HttpServer::new(move || {
App::new()
.app_data(state.clone())
.service(create_user)
.service(list_users)
.service(get_user)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
5. Extractors (Extração Tipada)
Actix utiliza o conceito de extractors para injetar dados automaticamente no handler.
Tipos comuns:
| Extractor | Uso |
|---|---|
web::Json<T> | Body JSON |
web::Path<T> | Parâmetros de rota |
web::Query<T> | Query string |
web::Data<T> | Estado global |
HttpRequest | Request completo |
Exemplo Query String
use serde::Deserialize;
#[derive(Deserialize)]
struct Pagination {
page: u32,
limit: u32,
}
#[get("/items")]
async fn list_items(query: web::Query<Pagination>) -> HttpResponse {
HttpResponse::Ok().body(format!(
"Page: {}, Limit: {}",
query.page, query.limit
))
}
6. Middleware
Middleware intercepta requests/responses.
Logger
use actix_web::middleware::Logger;
HttpServer::new(|| {
App::new()
.wrap(Logger::default())
})
Ativar:
RUST_LOG=info cargo run
7. Tratamento de Erros Customizado
use actix_web::{ResponseError, HttpResponse};
use thiserror::Error;
#[derive(Error, Debug)]
enum ApiError {
#[error("Usuário não encontrado")]
NotFound,
}
impl ResponseError for ApiError {
fn error_response(&self) -> HttpResponse {
match self {
ApiError::NotFound => HttpResponse::NotFound().body(self.to_string()),
}
}
}
Uso:
async fn example() -> Result<HttpResponse, ApiError> {
Err(ApiError::NotFound)
}
8. Integração com Banco (Exemplo com SQLx)
sqlx = { version = "0.7", features = ["runtime-tokio", "postgres"] }
use sqlx::PgPool;
struct AppState {
db: PgPool,
}
Query real:
let user = sqlx::query_as!(
User,
"SELECT id, name FROM users WHERE id = $1",
user_id
)
.fetch_one(&data.db)
.await?;
9. Performance e Arquitetura
Modelo de Concorrência
- Worker threads independentes
- Event loop async
- Sem GC
- Uso extensivo de zero-cost abstractions
Quando usar
✔ APIs de alta performance ✔ Microservices ✔ Sistemas com alta concorrência
Quando não usar
✖ Protótipos rápidos (complexidade maior que Node) ✖ Equipe sem familiaridade com Rust
10. Organização Recomendada de Projeto
src/
├── main.rs
├── handlers/
├── models/
├── errors/
├── services/
└── routes.rs
Separar:
- Lógica de negócio (services)
- Handlers HTTP
- Modelos
- Camada de persistência
11. Comparação Conceitual
| Framework | Linguagem | Modelo | Performance |
|---|---|---|---|
| Actix Web | Rust | Async + Actors | Muito alta |
| Axum | Rust | Tower + Async | Alta |
| Express | Node | Event Loop | Média |
| FastAPI | Python | Async | Alta |