Depot

Depot est utilisé pour stocker les données temporaires impliquées dans une seule requête. Les intergiciels peuvent placer les données temporaires qu'ils traitent dans le Depot pour une utilisation par les programmes ultérieurs.

Lorsqu'un serveur reçoit une requête d'un navigateur client, il crée une instance de Depot. Cette instance est détruite après que tous les intergiciels et Handler ont terminé le traitement de la requête.

Par exemple, nous pouvons définir current_user dans un intergiciel de connexion, puis lire les informations de l'utilisateur actuel dans les intergiciels ou Handler suivants.

Compréhension rapide

Depot est utilisé pour stocker et partager des données pendant le traitement des requêtes. Il implémente un conteneur de données type-safe qui prend en charge deux principaux modes d'utilisation :

  1. Stockage Clé-Valeur : Accéder aux valeurs associées à des clés de chaîne via les méthodes insert/get.
  2. Injection de type : Stocker et récupérer des valeurs basées sur le type via les méthodes inject/obtain.

Comme le montrent les exemples, Depot est particulièrement utile pour transmettre des données entre les intergiciels et les gestionnaires. Les intergiciels peuvent définir des valeurs dans Depot (telles que les informations utilisateur, l'état d'authentification), et les gestionnaires ultérieurs peuvent récupérer ces valeurs sans calculs ou requêtes redondants. La conception de Depot garantit la cohérence et l'accessibilité des données tout au long de la chaîne de traitement des requêtes, ce qui en fait un outil central pour construire des applications web complexes.

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

Définition et récupération de données via insert et get

Comme indiqué ci-dessus, vous pouvez insérer une clé et une valeur dans Depot en utilisant insert. Pour les valeurs de ce type, vous pouvez les récupérer directement en utilisant get.

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

Si la clé n'existe pas, ou si la clé existe mais que le type ne correspond pas, cela retourne None.

Définition et récupération de données via inject et obtain

Parfois, il existe des scénarios où une instance unique existe pour un type sans avoir besoin de la relier à une clé spécifique. Vous pouvez utiliser inject pour insérer des données, puis utiliser obtain pour les récupérer. Ces méthodes ne nécessitent pas que vous fournissiez une clé.

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

Aperçu des méthodes de la structure Depot

CatégorieMéthodeDescription
Création/Capaciténew()Crée un Depot vide
with_capacity(capacity)Crée un Depot avec la capacité spécifiée
capacity()Obtient la capacité
inner()Obtient une référence au HashMap interne
Injection/Récupération par typeinject<V>(value)Injecte une valeur par type
obtain<T>()Récupère une référence à la valeur injectée
obtain_mut<T>()Récupère une référence mutable à la valeur injectée
contains<T>()Vérifie si un type spécifique est contenu
scrape<T>()Supprime et retourne la valeur injectée
Opérations Clé-Valeurinsert(key, value)Insère une paire clé-valeur
get<V>(key)Récupère une référence à la valeur associée à la clé
get_mut<V>(key)Récupère une référence mutable à la valeur associée à la clé
contains_key(key)Vérifie si une clé spécifique est contenue
remove<V>(key)Supprime la clé et retourne la valeur
delete(key)Supprime la paire clé-valeur