Depot

Depot 是用于保存一次请求中涉及到的临时数据. 中间件可以将自己处理的临时数据放入 Depot, 供后续程序使用.

当一个服务器接收到一个客户浏览器发来的请求后会创建一个 Depot 的实例. 这个实例会在所有的中间件和 Handler 处理完请求后被销毁.

比如说, 我们可以在登录的中间件中设置 current_user, 然后在后续的中间件或者 Handler 中读取当前用户信息.

快速理解

Depot 用于在请求处理过程中存储和共享数据。它实现了一个类型安全的数据容器,支持两种主要使用模式:

  1. 键值存储:通过 insert/get 方法存取字符串键关联的值
  2. 类型注入:通过 inject/obtain 方法基于类型存取值

如示例所示,Depot 特别适用于在中间件和处理程序之间传递数据。中间件可以在 Depot 中设置值(如用户信息、认证状态),后续处理程序可以获取这些值,无需重复计算或查询。Depot 的设计确保了在整个请求处理链中数据的一致性和可访问性,是构建复杂 Web 应用的核心工具。

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;
}

通过insertget 设置和取出数据

正如上面所示, 可以通过 insertkeyvalue 插入到 Depot 中. 对于这一类型的值, 直接用 get 取出.

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

如果不存在这个 key, 或者 key 存在, 但是类型不匹配, 则返回 None.

通过injectobtain 设置和取出数据

有时, 存在一些不需要关系具体 key, 对于这种类型也存在唯一实例的情况. 可以使用 inject 插入数据, 然后使用 obtain 取出数据. 它们不需要你提供 key.

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)删除键值对