В то время, будучи новичком, я понял, что мне сложно освоить существующие фреймворки, такие как actix-web и Rocket. Когда я захотел переписать свой веб-сервис с Go на Rust, оказалось, что каждый фреймворк выглядит сложнее, чем аналоги в Go. Учитывая, что Rust сам по себе имеет крутую кривую обучения, зачем делать веб-фреймворки ещё сложнее?
Когда Tokio представил фреймворк Axum, я обрадовался, думая, что больше не придётся поддерживать свой собственный веб-фреймворк. Однако на практике Axum оказался обманчиво простым: избыточная работа с типами и дженериками требовала глубокого понимания Rust и написания множества сложных шаблонных конструкций даже для простого middleware.
Поэтому я решил продолжить развивать свой особенный (удобный, функциональный и подходящий для новичков) веб-фреймворк.
Несмотря на простоту, Salvo обладает полным набором мощных функций и может считаться одним из сильнейших в экосистеме Rust. При этом его изучение и использование интуитивно понятны — никакой болезненной адаптации.
Идеален для начинающих изучать Rust: CRUD-операции должны быть простыми и привычными. С Salvo такие задачи решаются так же легко, как и в других языках (например, Express, Koa, Gin, Flask), а в чём-то даже проще и элегантнее.
Подходит для production-сред, где требуется надёжный и быстрый сервер. Хотя Salvo ещё не достиг версии 1.0, его основные компоненты прошли многолетнюю итерационную доработку, стабильны, а проблемы оперативно исправляются.
Создан для вас, даже если ваши волосы уже не так густы, но продолжают редеть с каждым днём.
Большинство низкоуровневых задач уже решены в Hyper, поэтому для стандартных потребностей разумно строить фреймворк на его основе. Salvo — не исключение. Его ядро — это мощная и гибкая система маршрутизации, дополненная часто используемыми функциями, такими как Acme, OpenAPI, JWT-аутентификация и другие.
В Salvo унифицированы обработчики (Handler) и промежуточное ПО (Middleware). Middleware — это тоже Handler, который добавляется в Router через метод hoop. По сути, и Middleware, и Handler обрабатывают запросы (Request) и могут записывать данные в ответ (Response). Handler принимает три параметра: Request, Depot (для временных данных обработки) и Response.
Для удобства можно опускать неиспользуемые параметры или менять их порядок:
API системы маршрутизации также прост, но функционален. В большинстве случаев достаточно работать только с типом Router.
Кроме того, если структура реализует определённые трейты, Salvo автоматически генерирует документацию OpenAPI, извлекает параметры, обрабатывает ошибки и возвращает понятные сообщения. Это делает написание обработчиков таким же простым, как и обычных функций. В следующих уроках мы подробно разберём эти возможности. Вот пример:
Здесь JsonBody<CreateOrUpdateMessageLog>
автоматически парсит JSON из тела запроса (поддерживаются несколько источников и вложенные типы), а макрос #[endpoint]
генерирует документацию OpenAPI, упрощая извлечение параметров и обработку ошибок.
На мой взгляд, система маршрутизации Salvo отличается от других. Router можно организовать линейно или в виде дерева. Различают дерево бизнес-логики и дерево URL-путей. Первое отражает структуру бизнес-процессов и не всегда совпадает со вторым.
Обычно маршруты пишут так:
Часто просмотр списка статей и отдельной статьи не требует авторизации, а создание, редактирование и удаление — да. Вложенная маршрутизация Salvo идеально подходит для таких сценариев. Можно сгруппировать публичные маршруты:
А защищённые маршруты объединить с middleware для проверки аутентификации:
Хотя оба Router имеют одинаковый path("articles")
, их можно добавить к одному родительскому маршруту. Итоговая структура будет выглядеть так:
{id}
соответствует сегменту пути. Если ID статьи — это число, можно ограничить шаблон регулярным выражением: r"{id:/\d+/}"
.