Совместимость с Tower middleware

Salvo предоставляет поддержку совместимости с экосистемой Tower через функцию tower-compat. Подробности API смотрите в документации.

Ключевые концепции Tower

Tower — это библиотека абстракций сервисов, основанная на двух основных трейтах:

Трейт Service

pub trait Service<Request> {
    type Response;
    type Error;
    type Future: Future<Output = Result<Self::Response, Self::Error>>;

    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>;
    fn call(&mut self, req: Request) -> Self::Future;
}

Service отвечает за обработку запросов и возврат ответов, аналогично обработчикам в Salvo.

Трейт Layer

pub trait Layer<S> {
    type Service;
    fn layer(&self, inner: S) -> Self::Service;
}

Layer используется для оборачивания сервисов и добавления дополнительной функциональности, аналогично middleware в Salvo.

Поддержка совместимости в Salvo

Salvo предоставляет две ключевые реализации трейтов для совместимости с экосистемой Tower:

  • TowerLayerCompat: преобразует Tower Layer в Salvo Handler, позволяя использовать его как Hoop (middleware)
  • TowerServiceCompat: преобразует Tower Service в Salvo Handler

Пример использования:

// Используем RateLimitLayer из Tower и преобразуем в совместимый с Salvo формат через метод compat()
let limit = RateLimitLayer::new(5, Duration::from_secs(30)).compat();
let router = Router::new().hoop(limit).get(hello);

Пример кода

main.rs
Cargo.toml
with-tower/src/main.rs
use salvo::prelude::*;
use tokio::time::Duration;
use tower::limit::RateLimitLayer;

#[handler]
async fn hello() -> &'static str {
    "Hello World"
}

#[tokio::main]
async fn main() {
    tracing_subscriber::fmt().init();

    let limit = RateLimitLayer::new(5, Duration::from_secs(30)).compat();
    let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
    let router = Router::new().hoop(limit).get(hello);
    Server::new(acceptor).serve(router).await;
}