Depot

Depot 是用來儲存一次請求中相關的臨時數據。中間件可以將其處理的臨時數據存入 Depot,以便後續的程序調用。

當伺服器接收到來自客戶端瀏覽器的請求時,會創建一個 Depot 實例。該實例會在所有中間件和 Handler 完成請求處理後被銷毀。

例如,我們可以在用戶認證的中間件中設置 current_user,隨後在後面的中間件或 Handler 中讀取當前用戶的資訊。

use salvo::prelude::*;

#[handler]
async fn set_user(depot: &mut Depot) {
    depot.insert("current_user", "Elon Musk");
}
#[handler]
async fn hello(depot: &mut Depot) -> String {
    // Notice: Don't use String here, because you inserted a &str.
    let user = depot.get::<&str>("current_user").copied().unwrap();
    format!("Hey {}, I love your money and girls!", user)
}

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

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

    let acceptor = TcpListener::new("127.0.0.1:5800").bind().await;
    Server::new(acceptor).serve(router).await;
}
[package]
name = "example-use-depot"
version = "0.1.0"
edition = "2021"
publish = false

[dependencies]
salvo.workspace = true
tokio = { version = "1", features = ["macros"] }
tracing = "0.1"
tracing-subscriber = "0.3"

通過 insertget 設置和取出數據

正如前文提到的,您可以使用 insert 方法將 key 與對應的 value 加入至 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>();