Depot

Depot — это структура для хранения временных данных, связанных с обработкой одного запроса. Промежуточное ПО может сохранять обработанные данные в Depot для последующего использования другими компонентами.

При получении запроса от клиентского браузера сервер создает экземпляр Depot. Этот экземпляр существует в течение всего времени обработки запроса промежуточным ПО и Handler, после чего уничтожается.

Например, в промежуточном ПО аутентификации можно установить current_user, а затем в последующих обработчиках или промежуточном ПО получить информацию о текущем пользователе.

Быстрое понимание

Depot предназначен для хранения и обмена данными в процессе обработки запроса. Он реализует типобезопасный контейнер данных с двумя основными режимами работы:

  1. Хранилище ключ-значение: методы insert/get для работы со значениями по строковым ключам
  2. Внедрение по типу: методы inject/obtain для работы со значениями на основе их типа

Как показано в примерах, Depot особенно полезен для передачи данных между промежуточным ПО и обработчиками. Промежуточное ПО может сохранять значения (например, информацию о пользователе, статус аутентификации), которые затем могут быть получены последующими обработчиками без повторных вычислений или запросов. Дизайн Depot гарантирует согласованность и доступность данных на протяжении всей цепочки обработки запроса, что делает его ключевым инструментом для сложных веб-приложений.

main.rs
Cargo.toml
use-depot/src/main.rs
use salvo::prelude::*;

#[handler]
async fn set_user(depot: &mut Depot) {
    depot.insert("user", "client");
}
#[handler]
async fn hello(depot: &mut Depot) -> String {
    format!(
        "Hello {}",
        depot.get::<&str>("user").copied().unwrap_or_default()
    )
}

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

    let router = Router::new().hoop(set_user).goal(hello);

    let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
    Server::new(acceptor).serve(router).await;
}

Установка и получение данных черезinsert иget

Как показано выше, вы можете вставить пару key и value в Depot с помощью insert. Для таких значений используется прямое получение через get.

depot.insert("a", "b");
assert_eq!(depot.get::<&str>("a").copied().unwrap(), "b")

Если ключ не существует или тип значения не соответствует ожидаемому, возвращается None.

Установка и получение данных черезinject иobtain

В некоторых случаях существуют значения, для которых не требуется конкретный ключ — когда для данного типа существует только один экземпляр. Для таких значений можно использовать inject для вставки и obtain для получения. Эти методы не требуют указания ключа.

depot.inject(Config::new());
depot.obtain::<Config>();

Обзор методов структуры Depot

КатегорияМетодОписание
Создание/ёмкостьnew()Создает пустой Depot
with_capacity(capacity)Создает Depot с указанной ёмкостью
capacity()Возвращает текущую ёмкость
inner()Возвращает ссылку на внутренний HashMap
Внедрение/получение по типуinject<V>(value)Внедряет значение по типу
obtain<T>()Получает ссылку на внедренное значение
obtain_mut<T>()Получает изменяемую ссылку на внедренное значение
contains<T>()Проверяет наличие значения типа
scrape<T>()Удаляет и возвращает внедренное значение
Операции с ключамиinsert(key, value)Вставляет пару ключ-значение
get<V>(key)Получает ссылку на значение по ключу
get_mut<V>(key)Получает изменяемую ссылку на значение по ключу
contains_key(key)Проверяет наличие ключа
remove<V>(key)Удаляет и возвращает значение по ключу
delete(key)Удаляет пару ключ-значение