<h2>Introdução ao Axum e sua Arquitetura</h2>
<p>Axum é um framework web moderno construído sobre a stack assíncrona de Rust, particularmente o Tokio. Diferentemente de frameworks tradicionais, Axum trabalha com composição de componentes através de towers e middlewares, permitindo máxima flexibilidade e performance. O framework é mantido pela equipe Tokio e representa o estado da arte em desenvolvimento web com Rust, sendo ideal para APIs REST que demandam alta concorrência e baixa latência.</p>
<p>A arquitetura de Axum segue o padrão de roteadores compostos e handlers tipados. Cada rota é associada a um handler function que recebe extratos da requisição (como JSON bodies ou parâmetros de path) de forma type-safe. Isso significa que erros de tipo são capturados em tempo de compilação, não em runtime como em muitas linguagens dinâmicas.</p>
<h2>Configurando seu Primeiro Projeto</h2>
<p>Comece criando um novo projeto Rust e adicionando as dependências essenciais no <code>Cargo.toml</code>:</p>
<pre><code class="language-toml">[package]
name = "api-axum"
version = "0.1.0"
edition = "2021"
[dependencies]
axum = "0.7"
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"</code></pre>
<p>Agora crie uma API simples com um endpoint que retorna JSON:</p>
<pre><code class="language-rust">use axum::{
routing::{get, post},
Json, Router,
};
use serde::{Deserialize, Serialize};
use std::net::SocketAddr;
#[derive(Serialize, Deserialize)]
struct User {
id: u32,
name: String,
email: String,
}
async fn create_user(Json(payload): Json<User>) -> Json<User> {
Json(User {
id: 1,
name: payload.name,
email: payload.email,
})
}
async fn list_users() -> Json<Vec<User>> {
Json(vec![
User {
id: 1,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
},
])
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/users", post(create_user))
.route("/users", get(list_users));
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
axum::serve(listener, app).await.unwrap();
}</code></pre>
<p>Execute com <code>cargo run</code> e teste com curl: <code>curl -X POST http://localhost:3000/users -H "Content-Type: application/json" -d '{"id":1,"name":"Bob","email":"bob@test.com"}'</code></p>
<h2>Roteamento Avançado e Handlers Tipados</h2>
<h3>Parâmetros de Path e Query</h3>
<p>Axum permite extrair parâmetros diretamente através do sistema de tipos. Para parâmetros de path, use <code>:param</code> na rota:</p>
<pre><code class="language-rust">use axum::extract::Path;
async fn get_user(Path(user_id): Path<u32>) -> Json<User> {
Json(User {
id: user_id,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
})
}
let app = Router::new()
.route("/users/:id", get(get_user));</code></pre>
<p>Para query parameters, use <code>Query</code>:</p>
<pre><code class="language-rust">use axum::extract::Query;
use serde::Deserialize;
#[derive(Deserialize)]
struct ListParams {
limit: Option<u32>,
offset: Option<u32>,
}
async fn list_users_paginated(
Query(params): Query<ListParams>,
) -> Json<Vec<User>> {
let limit = params.limit.unwrap_or(10);
// Implementar lógica de paginação
Json(vec![])
}
let app = Router::new()
.route("/users", get(list_users_paginated));</code></pre>
<h3>Estados Compartilhados</h3>
<p>Aplicações reais precisam compartilhar estado entre handlers. Use <code>State</code> para injetar dados:</p>
<pre><code class="language-rust">use axum::extract::State;
use std::sync::Arc;
use std::sync::Mutex;
type SharedUsers = Arc<Mutex<Vec<User>>>;
async fn create_user_with_state(
State(users): State<SharedUsers>,
Json(payload): Json<User>,
) -> Json<User> {
let mut users_lock = users.lock().unwrap();
users_lock.push(payload.clone());
Json(payload)
}
#[tokio::main]
async fn main() {
let users_state: SharedUsers = Arc::new(Mutex::new(vec![]));
let app = Router::new()
.route("/users", post(create_user_with_state))
.with_state(users_state);
// ... rest do código
}</code></pre>
<h2>Tratamento de Erros e Middlewares</h2>
<h3>Custom Error Responses</h3>
<p>Defina tipos de erro que implementem <code>IntoResponse</code> para respostas HTTP customizadas:</p>
<pre><code class="language-rust">use axum::{
http::StatusCode,
response::{IntoResponse, Response},
Json,
};
enum ApiError {
UserNotFound,
InvalidInput,
}
impl IntoResponse for ApiError {
fn into_response(self) -> Response {
let (status, error_message) = match self {
ApiError::UserNotFound => (StatusCode::NOT_FOUND, "User not found"),
ApiError::InvalidInput => (StatusCode::BAD_REQUEST, "Invalid input"),
};
(status, Json(serde_json::json!({"error": error_message}))).into_response()
}
}
async fn get_user_safe(
Path(user_id): Path<u32>,
) -> Result<Json<User>, ApiError> {
if user_id == 0 {
return Err(ApiError::InvalidInput);
}
Ok(Json(User {
id: user_id,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
}))
}</code></pre>
<h3>Middlewares com Tower</h3>
<p>Axum integra perfeitamente com Tower para adicionar funcionalidades cross-cutting:</p>
<pre><code class="language-rust">use tower_http::cors::CorsLayer;
use tower_http::trace::TraceLayer;
let app = Router::new()
.route("/users", post(create_user))
.route("/users/:id", get(get_user_safe))
.layer(TraceLayer::new_for_http())
.layer(CorsLayer::permissive());</code></pre>
<p>Adicione ao <code>Cargo.toml</code>: <code>tower-http = { version = "0.5", features = ["cors", "trace"] }</code></p>
<h2>Conclusão</h2>
<p>Você aprendeu que <strong>Axum oferece type-safety e composição elegante</strong> para construir APIs REST robustas, permitindo que erros sejam capturados em compilação. <strong>O roteamento é intuitivo e as extrações de dados automáticas</strong> reduzem boilerplate significativamente. Finalmente, <strong>a integração com Tower e o ecosistema Tokio</strong> posiciona Axum como escolha ideal para aplicações de alta performance em produção.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://docs.rs/axum/latest/axum/" target="_blank" rel="noopener noreferrer">Documentação oficial Axum</a></li>
<li><a href="https://tokio.rs/" target="_blank" rel="noopener noreferrer">Tokio Runtime Guide</a></li>
<li><a href="https://docs.rs/tower/latest/tower/" target="_blank" rel="noopener noreferrer">Tower Middleware Documentation</a></li>
<li><a href="https://rust-lang.github.io/async-book/" target="_blank" rel="noopener noreferrer">Rust Book - Async Programming</a></li>
<li><a href="https://serde.rs/" target="_blank" rel="noopener noreferrer">Serde Serialization Framework</a></li>
</ul>