Depot

O Depot é utilizado para armazenar dados temporários envolvidos em uma única requisição. O middleware pode colocar os dados temporários que processa no Depot para uso por programas subsequentes.

Quando um servidor recebe uma requisição de um navegador cliente, ele cria uma instância do Depot. Esta instância é destruída após todos os middlewares e Handler terminarem de processar a requisição.

Por exemplo, podemos definir current_user em um middleware de login e, em seguida, ler as informações do usuário atual em middleware ou Handler subsequentes.

Compreensão Rápida

O Depot é usado para armazenar e compartilhar dados durante o processamento da requisição. Ele implementa um contêiner de dados com segurança de tipos que suporta dois padrões principais de uso:

  1. Armazenamento Chave-Valor: Acessa valores associados a chaves de string através dos métodos insert/get.
  2. Injeção de Tipo: Armazena e recupera valores com base no tipo através dos métodos inject/obtain.

Como mostrado nos exemplos, o Depot é particularmente útil para passar dados entre middleware e handlers. O middleware pode definir valores no Depot (como informações do usuário, status de autenticação), e handlers subsequentes podem recuperar esses valores sem cálculos ou consultas redundantes. O design do Depot garante a consistência e acessibilidade dos dados em toda a cadeia de processamento da requisição, tornando-o uma ferramenta central para construir aplicações web complexas.

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

Configurando e Recuperando Dados via insert e get

Como mostrado acima, você pode inserir chave e valor no Depot usando insert. Para valores desse tipo, você pode recuperá-los diretamente usando get.

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

Se a chave não existir, ou se a chave existir mas o tipo não corresponder, ele retorna None.

Configurando e Recuperando Dados via inject e obtain

Às vezes, há cenários em que existe uma instância única para um tipo sem necessidade de relacioná-la a uma chave específica. Você pode usar inject para inserir dados e, em seguida, usar obtain para recuperá-los. Esses métodos não exigem que você forneça uma chave.

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

Visão Geral dos Métodos da Struct Depot

CategoriaMétodoDescrição
Criação/Capacidadenew()Cria um Depot vazio
with_capacity(capacity)Cria um Depot com a capacidade especificada
capacity()Obtém a capacidade
inner()Obtém uma referência ao HashMap interno
Injeção/Recuperação por Tipoinject<V>(value)Injeta um valor por tipo
obtain<T>()Recupera uma referência ao valor injetado
obtain_mut<T>()Recupera uma referência mutável ao valor injetado
contains<T>()Verifica se um tipo específico está contido
scrape<T>()Remove e retorna o valor injetado
Operações Chave-Valorinsert(key, value)Insere um par chave-valor
get<V>(key)Recupera uma referência ao valor associado à chave
get_mut<V>(key)Recupera uma referência mutável ao valor associado à chave
contains_key(key)Verifica se uma chave específica está contida
remove<V>(key)Remove a chave e retorna o valor
delete(key)Exclui o par chave-valor