Salvo: Когда Rust становится простым и быстрым для веба
"Rust — это сложно", — слышали такое? Многие разработчики, наслышанные о крутой производительности, безопасности и надежности Rust, часто останавливаются перед высоким порогом входа, особенно когда речь заходит о веб-разработке. Казалось бы, чтобы писать на Rust, нужно быть гуру системного программирования. А что, если я скажу, что есть фреймворк, который делает создание бэкендов на Rust не просто быстрым, а еще и удивительно простым, позволяя сосредоточиться на логике, а не на борьбе с компилятором?
Позвольте представить вам Salvo — асинхронный веб-фреймворк, который стремится разрушить стереотипы о сложности Rust в вебе. Он создан для тех, кто хочет использовать всю мощь языка, но при этом ценит элегантность и простоту API.
Что такое Salvo и для кого он?
Salvo — это современный, высокопроизводительный веб-фреймворк, написанный на Rust. Он построен на базе проверенных временем компонентов, таких как Hyper 1 для работы с HTTP и Tokio для асинхронного выполнения. Это означает, что под капотом у вас будет надежная и быстрая основа, а сверху — удобный и интуитивно понятный интерфейс.
Кому подойдет Salvo?
- Новичкам в Rust-вебе: Если вы только начинаете осваивать Rust для бэкенда, Salvo значительно упростит первые шаги благодаря своей философии "простоты".
- Опытным Rust-разработчикам: Для создания высоконагруженных API, микросервисов или полноценных веб-приложений, где важна каждая миллисекунда и каждый байт памяти.
- Всем, кто ценит производительность и безопасность: Salvo позволяет писать код, который по умолчанию безопасен и при этом демонстрирует впечатляющие результаты в бенчмарках.
Ключевые возможности Salvo: От простоты до мощи
Давайте погрузимся в то, что делает Salvo по-настоящему интересным и практичным для разработчиков.
HTTP3 и автоматический TLS с ACME: Будущее уже здесь!
Представьте: вы запускаете свой веб-сервис, и он сразу же поддерживает новейший протокол HTTP3, а также автоматически получает и обновляет TLS-сертификаты от Let's Encrypt. Звучит как магия, не так ли? Salvo делает это реальностью всего в нескольких строках кода.
Это не просто "модная фича", это практическая польза: HTTP3 значительно улучшает производительность и надежность соединения, особенно в условиях нестабильных сетей, а автоматический TLS избавляет вас от рутины по управлению сертификатами.
use salvo::prelude::*;
#[handler]
async fn hello(res: &mut Response) {
res.render(Text::Plain("Hello World"));
}
#[tokio::main]
async fn main() {
let mut router = Router::new().get(hello);
let listener = TcpListener::new("0.0.0.0:443")
.acme()
.add_domain("test.salvo.rs") // Replace this domain name with your own.
.http01_challenge(&mut router).quinn("0.0.0.0:443");
let acceptor = listener.join(TcpListener::new("0.0.0.0:80")).bind().await;
Server::new(acceptor).serve(router).await;
}
Middleware и Handler: Одно лицо, максимум гибкости
Одна из самых приятных особенностей Salvo — это унифицированный подход к обработчикам (handlers) и промежуточному ПО (middleware). В Salvo middleware — это просто еще один handler! Это значит, что вам не нужно изучать сложные концепции, такие как ассоциированные типы или дженерики, чтобы написать свою логику, которая будет выполняться до или после основного обработчика. Если вы можете написать функцию, вы можете написать middleware!
Такой подход значительно упрощает разработку, тестирование и повторное использование кода. Например, добавить кастомный заголовок к каждому ответу становится элементарно:
use salvo::http::header::{self, HeaderValue};
use salvo::prelude::*;
#[handler]
async fn add_header(res: &mut Response) {
res.headers_mut()
.insert(header::SERVER, HeaderValue::from_static("Salvo"));
}
// Затем просто добавляем его к роутеру:
// Router::new().hoop(add_header).get(hello)
Древовидная маршрутизация: Структура и контроль
Знакомая ситуация: часть API требует авторизации, а другая доступна всем? Salvo предлагает элегантное решение с помощью своей древовидной системы маршрутизации. Вы можете вкладывать роутеры друг в друга, и каждый вложенный роутер может иметь свой собственный набор middleware. Это позволяет очень гибко управлять логикой доступа и обработки запросов.
// Роуты без авторизации
Router::with_path("articles")
.get(list_articles)
.push(Router::with_path("{id}").get(show_article));
// Роуты, требующие авторизации
Router::with_path("articles")
.hoop(auth_check) // Middleware для проверки авторизации
.push(Router::with_path("{id}").patch(edit_article).delete(delete_article));
// Объединение в один корневой роутер
Router::new()
.push(
Router::with_path("articles")
.get(list_articles)
.push(Router::with_path("{id}").get(show_article)),
)
.push(
Router::with_path("articles")
.hoop(auth_check)
.push(Router::with_path("{id}").patch(edit_article).delete(delete_article)),
);
Кстати, Salvo также поддерживает мощные возможности для работы с параметрами пути, включая регулярные выражения и именованные сегменты, что дает вам полный контроль над структурой URL.
Удобное извлечение данных из запроса: Минимум бойлерплейта
Сколько раз вы писали ручной парсинг JSON или данных формы? Salvo избавляет от этой рутины, позволяя легко извлекать данные из различных источников запроса (тело, параметры пути, query-параметры) и автоматически связывать их с вашими Rust-структурами. Просто добавьте #[derive(Extractible)] и укажите источники данных.
use serde::{Deserialize, Serialize};
use salvo::prelude::*;
use salvo::extract::Extractible;
#[derive(Serialize, Deserialize, Extractible, Debug)]
/// По умолчанию получаем поля из тела запроса.
#[salvo(extract(default_source(from = "body")))]
struct GoodMan<'a> {
/// ID получаем из параметра пути и автоматически парсим в i64.
#[salvo(extract(source(from = "param")))]
id: i64,
/// Можно использовать ссылочные типы для избежания копирования памяти.
username: &'a str,
first_name: String,
last_name: String,
}
#[handler]
async fn edit<'a>(good_man: GoodMan<'a>) -> Json<GoodMan<'a>> {
// Теперь `good_man` содержит все необходимые данные, готовые к использованию!
Json(good_man)
}
Это значительно ускоряет разработку API, делая код чище и понятнее.
OpenAPI из коробки: Документация без усилий
Поддержание актуальной документации API — головная боль для многих команд. Salvo решает эту проблему, предлагая отличную поддержку OpenAPI. Вы можете автоматически генерировать спецификацию OpenAPI на основе ваших обработчиков и даже интегрировать Swagger UI, чтобы разработчики могли легко исследовать и тестировать ваш API.
use serde::{Deserialize, Serialize};
use salvo::prelude::*;
use salvo::oapi::ToSchema;
#[derive(Serialize, Deserialize, ToSchema, Debug)]
struct MyObject<T: ToSchema + std::fmt::Debug> {
value: T,
}
#[endpoint]
async fn use_string(body: JsonBody<MyObject<String>>) -> String {
format!("{:?}", body)
}
// ... другие endpoint'ы
#[tokio::main]
async fn main() {
tracing_subscriber::fmt().init();
let router = Router::new()
.push(Router::with_path("i32").post(use_i32))
.push(Router::with_path("u64").post(use_u64))
.push(Router::with_path("string").post(use_string));
let doc = OpenApi::new("test api", "0.0.1").merge_router(&router);
let router = router
.push(doc.into_router("/api-doc/openapi.json"))
.push(SwaggerUi::new("/api-doc/openapi.json").into_router("swagger-ui"));
let acceptor = TcpListener::new("127.0.0.1:8698").bind().await;
Server::new(acceptor).serve(router).await;
}
Под капотом: Скорость и надежность Rust
Salvo не просто прост в использовании, он еще и невероятно быстр. Основанный на Hyper и Tokio, он наследует их производительность и асинхронные возможности. Интересно, что в проекте используется значок unsafe forbidden, что подчеркивает приверженность разработчиков к безопасности, избегая потенциально опасных unsafe блоков Rust.
Если вам нужны доказательства, Salvo регулярно участвует в известных бенчмарках веб-фреймворков, таких как web-frameworks-benchmark и TechEmpower, где показывает отличные результаты.
Salvo уже используется в реальных проектах, что говорит о его зрелости и надежности. Среди компаний, которые доверяют Salvo, можно найти такие проекты, как:
![]() |
![]() |
Начните свой проект с Salvo CLI
Чтобы максимально упростить старт, разработчики Salvo предлагают удобный инструмент командной строки — salvo-cli. С его помощью вы можете быстро создать новый проект Salvo, выбрав нужный шаблон: веб-API, сайт, интеграцию с базами данных (SQLite, PostgreSQL, MySQL через SQLx, SeaORM, Diesel, Rbatis) и базовые middleware.
Установка и создание проекта:
cargo install salvo-cli
salvo new project_name
Выводы: Стоит ли попробовать Salvo?
Salvo — это не просто еще один веб-фреймворк на Rust. Это попытка сделать мощь Rust доступной и приятной для широкого круга веб-разработчиков. Если вы искали способ писать высокопроизводительные, безопасные и современные бэкенды, не утопая в излишней сложности, Salvo определенно заслуживает вашего внимания.
Его унифицированный подход к middleware, гибкая маршрутизация, автоматическая генерация OpenAPI и поддержка HTTP3 с ACME делают его отличным выбором для создания чего угодно: от небольших микросервисов до крупных API-шлюзов. Попробуйте Salvo, и, возможно, вы откроете для себя Rust с совершенно новой, более дружелюбной стороны!

