Depot

Depot dient zur Speicherung temporärer Daten, die während einer Anfrage verarbeitet werden. Middleware kann ihre verarbeiteten temporären Daten im Depot ablegen, um sie für nachfolgende Programme verfügbar zu machen.

Wenn ein Server eine Anfrage von einem Client-Browser empfängt, wird eine Instanz von Depot erstellt. Diese Instanz wird nach der Bearbeitung der Anfrage durch alle Middleware und Handler zerstört.

Zum Beispiel können wir in einer Login-Middleware current_user setzen und dann in nachfolgender Middleware oder Handler die aktuellen Benutzerinformationen auslesen.

Schnelles Verständnis

Depot wird verwendet, um Daten während der Anfrageverarbeitung zu speichern und zu teilen. Es implementiert einen typsicheren Datencontainer, der zwei Hauptnutzungsmodi unterstützt:

  1. Schlüssel-Wert-Speicher: Zugriff auf Werte über Zeichenkettenschlüssel mit insert/get-Methoden
  2. Typeninjektion: Speichern und Abrufen von Werten basierend auf ihrem Typ mit inject/obtain-Methoden

Wie im Beispiel gezeigt, eignet sich Depot besonders für die Datenweitergabe zwischen Middleware und Handlern. Middleware kann Werte (wie Benutzerinformationen oder Authentifizierungsstatus) im Depot setzen, die nachfolgende Handler abrufen können, ohne sie erneut berechnen oder abfragen zu müssen. Das Design von Depot gewährleistet Datenkonsistenz und Zugänglichkeit während der gesamten Anfrageverarbeitungskette und ist ein zentrales Werkzeug für den Aufbau komplexer Webanwendungen.

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

Daten mitinsert undget setzen und abrufen

Wie oben gezeigt, können mit insert key und value in Depot eingefügt werden. Für Werte dieses Typs kann direkt mit get darauf zugegriffen werden.

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

Falls der key nicht existiert oder der key existiert, aber der Typ nicht übereinstimmt, wird None zurückgegeben.

Daten mitinject undobtain setzen und abrufen

Manchmal gibt es Fälle, in denen kein spezifischer key benötigt wird und für diesen Typ nur eine einzige Instanz existiert. Hier können inject zum Einfügen und obtain zum Abrufen der Daten verwendet werden. Diese Methoden erfordern keinen key.

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

Übersicht der Depot-Strukturmethoden

KategorieMethodeBeschreibung
Erstellung/Kapazitätnew()Erstellt ein leeres Depot
with_capacity(capacity)Erstellt ein Depot mit angegebener Kapazität
capacity()Ruft die Kapazität ab
inner()Ruft die Referenz auf die interne HashMap ab
Typeninjektion/Abrufinject<V>(value)Fügt einen Wert nach Typ ein
obtain<T>()Ruft die Referenz auf den eingefügten Wert ab
obtain_mut<T>()Ruft die veränderbare Referenz auf den eingefügten Wert ab
contains<T>()Prüft, ob ein bestimmter Typ enthalten ist
scrape<T>()Entfernt und gibt den eingefügten Wert zurück
Schlüssel-Wert-Operationeninsert(key, value)Fügt ein Schlüssel-Wert-Paar ein
get<V>(key)Ruft die Referenz auf den Wert zum Schlüssel ab
get_mut<V>(key)Ruft die veränderbare Referenz auf den Wert zum Schlüssel ab
contains_key(key)Prüft, ob ein bestimmter Schlüssel enthalten ist
remove<V>(key)Entfernt den Schlüssel und gibt den Wert zurück
delete(key)Löscht das Schlüssel-Wert-Paar