Depot

Depot 用於儲存單次請求處理過程中的臨時資料。中介軟體可將自身處理的臨時資料存入 Depot,供後續程式使用。

當伺服器接收來自客戶端瀏覽器的請求時,會建立一個 Depot 實例。此實例將在所有中介軟體與 Handler 完成請求處理後被銷毀。

舉例而言,我們可在登入中介軟體中設定 current_user,並在後續中介軟體或 Handler 中讀取當前使用者資訊。

快速理解

Depot 用於在請求處理過程中儲存與共享資料。它實作了型別安全的資料容器,支援兩種主要使用模式:

  1. 鍵值儲存:透過 insert/get 方法存取與字串鍵關聯的值
  2. 型別注入:透過 inject/obtain 方法基於型別存取值

如範例所示,Depot 特別適用於在中介軟體與處理程式之間傳遞資料。中介軟體可在 Depot 中設定值(如使用者資訊、認證狀態),後續處理程式可取得這些值,無需重複計算或查詢。Depot 的設計確保了在整個請求處理鏈中資料的一致性與可存取性,是建構複雜 Web 應用的核心工具。

main.rs
Cargo.toml
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:8698").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)刪除鍵值對