Depot

Depot is used to store temporary data involved in a single request. Middleware can place the temporary data it processes into the Depot for use by subsequent programs.

When a server receives a request from a client browser, it creates an instance of Depot. This instance is destroyed after all middleware and Handler have finished processing the request.

For example, we can set current_user in a login middleware and then read the current user information in subsequent middleware or Handler.

Quick Understanding

Depot is used to store and share data during request processing. It implements a type-safe data container that supports two main usage patterns:

  1. Key-Value Storage: Access values associated with string keys via insert/get methods.
  2. Type Injection: Store and retrieve values based on type via inject/obtain methods.

As shown in the examples, Depot is particularly useful for passing data between middleware and handlers. Middleware can set values in Depot (such as user information, authentication status), and subsequent handlers can retrieve these values without redundant calculations or queries. The design of Depot ensures data consistency and accessibility throughout the entire request processing chain, making it a core tool for building complex web applications.

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

Setting and Retrieving Data via insert and get

As shown above, you can insert key and value into Depot using insert. For values of this type, you can directly retrieve them using get.

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

If the key does not exist, or if the key exists but the type does not match, it returns None.

Setting and Retrieving Data via inject and obtain

Sometimes, there are scenarios where a unique instance exists for a type without needing to relate to a specific key. You can use inject to insert data and then use obtain to retrieve it. These methods do not require you to provide a key.

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

Overview of Depot Struct Methods

CategoryMethodDescription
Creation/Capacitynew()Creates an empty Depot
with_capacity(capacity)Creates a Depot with the specified capacity
capacity()Gets the capacity
inner()Gets a reference to the internal HashMap
Type Injection/Retrievalinject<V>(value)Injects a value by type
obtain<T>()Retrieves a reference to the injected value
obtain_mut<T>()Retrieves a mutable reference to the injected value
contains<T>()Checks if a specific type is contained
scrape<T>()Removes and returns the injected value
Key-Value Operationsinsert(key, value)Inserts a key-value pair
get<V>(key)Retrieves a reference to the value associated with the key
get_mut<V>(key)Retrieves a mutable reference to the value associated with the key
contains_key(key)Checks if a specific key is contained
remove<V>(key)Removes the key and returns the value
delete(key)Deletes the key-value pair