Depot

Depot se utiliza para almacenar datos temporales involucrados en una única solicitud. El middleware puede colocar los datos temporales que procesa en el Depot para que los utilicen programas posteriores.

Cuando un servidor recibe una solicitud desde el navegador de un cliente, crea una instancia de Depot. Esta instancia se destruye después de que todo el middleware y el Handler hayan terminado de procesar la solicitud.

Por ejemplo, podemos establecer current_user en un middleware de inicio de sesión y luego leer la información del usuario actual en middleware o Handler posteriores.

Comprensión rápida

Depot se utiliza para almacenar y compartir datos durante el procesamiento de solicitudes. Implementa un contenedor de datos seguro en cuanto a tipos que admite dos patrones principales de uso:

  1. Almacenamiento clave-valor: Accede a valores asociados con claves de cadena mediante los métodos insert/get.
  2. Inyección de tipos: Almacena y recupera valores basados en el tipo mediante los métodos insert_typed/get_typed.

Como se muestra en los ejemplos, Depot es particularmente útil para pasar datos entre middleware y manejadores. El middleware puede establecer valores en Depot (como información del usuario, estado de autenticación), y los manejadores posteriores pueden recuperar estos valores sin cálculos o consultas redundantes. El diseño de Depot garantiza la consistencia y accesibilidad de los datos a lo largo de toda la cadena de procesamiento de solicitudes, convirtiéndolo en una herramienta central para construir aplicaciones web complejas.

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

Establecer y recuperar datos mediante insert y get

Como se muestra arriba, puedes insertar clave y valor en Depot usando insert. Para valores de este tipo, puedes recuperarlos directamente usando get.

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

Si la clave no existe, o si la clave existe pero el tipo no coincide, devuelve None.

Establecer y recuperar datos mediante insert_typed y get_typed

A veces, existen escenarios donde hay una instancia única para un tipo sin necesidad de relacionarla con una clave específica. Puedes usar insert_typed para insertar datos y luego usar get_typed para recuperarlos. Estos métodos no requieren que proporciones una clave.

depot.insert_typed(Config::new());
depot.get_typed::<Config>();

Resumen de métodos de la estructura Depot

CategoríaMétodoDescripción
Creación/Capacidadnew()Crea un Depot vacío
with_capacity(capacidad)Crea un Depot con la capacidad especificada
capacity()Obtiene la capacidad
inner()Obtiene una referencia al HashMap interno
Inyección/Recuperación de tiposinsert_typed<V>(valor)Inyecta un valor por tipo
get_typed<T>()Recupera una referencia al valor inyectado
get_typed_mut<T>()Recupera una referencia mutable al valor inyectado
contains_typed<T>()Verifica si contiene un tipo específico
remove_typed<T>()Elimina y devuelve el valor inyectado
Operaciones clave-valorinsert(clave, valor)Inserta un par clave-valor
get<V>(clave)Recupera una referencia al valor asociado con la clave
get_mut<V>(clave)Recupera una referencia mutable al valor asociado con la clave
contains_key(clave)Verifica si contiene una clave específica
remove<V>(clave)Elimina la clave y devuelve el valor
remove(clave).is_some()Elimina el par clave-valor