Dominar Esta Arte
Por Que Construir Este Framework
Como iniciante, enfrentei dificuldades para compreender frameworks existentes como actix-web e Rocket. Ao tentar reescrever um serviço web anterior em Go usando Rust, cada framework parecia mais complexo que os disponíveis em Go. Dada a já íngreme curva de aprendizado do Rust, por que complicar ainda mais os frameworks web?
Quando o Tokio introduziu o framework Axum, fiquei entusiasmado, pensando que finalmente poderia parar de manter meu próprio framework web. No entanto, logo percebi que, embora o Axum parecesse simples, ele exigia extensas ginásticas de tipos e definições genéricas. Criar até mesmo um middleware básico demandava profundo conhecimento de Rust e a escrita de grandes quantidades de código boilerplate obscuro.
Assim, decidi continuar mantendo meu framework web único — um que seja intuitivo, rico em recursos e amigável para iniciantes.
O Salvo É Para Você?
O Salvo é simples, mas abrangente e poderoso, possivelmente o mais forte no ecossistema Rust. Apesar de suas capacidades, ele permanece fácil de aprender e usar, poupando você de quaisquer dores de "auto-castração".
-
Ideal para iniciantes em Rust: Operações CRUD são comuns e, com o Salvo, tais tarefas parecem tão diretas quanto com frameworks em outras linguagens (por exemplo, Express, Koa, Gin, Flask). Em alguns aspectos, o Salvo é ainda mais abstrato e conciso.
-
Adequado para produção: Se você pretende implantar Rust em produção para servidores robustos e de alta velocidade, o Salvo atende perfeitamente. Embora ainda não esteja na versão 1.0, seus recursos principais passaram por anos de iteração, garantindo estabilidade e resolução oportuna de problemas.
-
Perfeito para você, especialmente se seus cabelos estão afinando e caindo diariamente.
Alcançando a Simplicidade
O Hyper lida com muitas implementações de baixo nível, tornando-o uma base confiável para necessidades gerais. O Salvo segue essa abordagem, oferecendo um sistema de roteamento poderoso e flexível, juntamente com recursos essenciais como Acme, OpenAPI e autenticação JWT.
O Salvo unifica Handlers e Middleware: Middleware é um Handler. Ambos são anexados ao Router via hoop. Essencialmente, eles processam Request e podem escrever dados em Response. Um Handler recebe três parâmetros: Request, Depot (para dados temporários durante o processamento da requisição) e Response.
Para conveniência, você pode omitir parâmetros desnecessários ou ignorar sua ordem.
A API de roteamento é excepcionalmente simples, mas poderosa. Para casos de uso típicos, você só precisa se concentrar no tipo Router.
Além disso, se uma struct implementar traits relevantes, o Salvo pode gerar automaticamente documentação OpenAPI, extrair parâmetros, lidar com erros de forma elegante e retornar mensagens amigáveis ao usuário. Isso torna a escrita de handlers tão intuitiva quanto escrever funções comuns. Exploraremos esses recursos em detalhes mais tarde. Aqui está um exemplo:
Neste exemplo, JsonBody<CreateOrUpdateMessageLog> analisa automaticamente JSON do corpo da requisição no tipo CreateOrUpdateMessageLog (suportando múltiplas fontes de dados e tipos aninhados). A macro #[endpoint] gera documentação OpenAPI para este endpoint, simplificando a extração de parâmetros e o tratamento de erros.
Sistema de Roteamento
Acredito que o sistema de roteamento do Salvo se destaca. Roteadores podem ser planos ou em árvore, distinguindo entre árvores de lógica de negócio e árvores de diretório de acesso. A árvore de lógica de negócio organiza roteadores com base nas necessidades do negócio, que podem não coincidir com a árvore de diretório de acesso.
Normalmente, as rotas são escritas assim:
Frequentemente, visualizar artigos e listá-los não requer login do usuário, mas criar, editar ou excluir artigos sim. O sistema de roteamento aninhado do Salvo lida com isso elegantemente. Podemos agrupar rotas públicas juntas:
Em seguida, agrupar rotas protegidas com middleware para autenticação:
Embora ambos os roteadores compartilhem o mesmo path("articles"), eles podem ser adicionados ao mesmo roteador pai, resultando em:
{id} corresponde a um segmento de caminho. Normalmente, um id de artigo é numérico, então podemos restringir a correspondência com uma regex: r"{id:/\d+/}".