Sessione

Middleware che fornisce supporto per Session.

Cos'è la Sessione

La sessione si riferisce ai dati utente memorizzati sul lato server, tipicamente utilizzati per tracciare lo stato dell'utente e memorizzare dati temporanei. Nelle applicazioni web, la sessione affronta la natura senza stato del protocollo HTTP, consentendo al server di riconoscere più richieste provenienti dallo stesso utente.

Utilizzo della Sessione in Salvo

In Salvo, il middleware Session offre un'API semplice per leggere e scrivere i dati della sessione. Il SessionDepot può essere utilizzato per ottenere un'istanza della sessione, mentre metodi come get, set e remove consentono di gestire i dati della sessione.

Casi d'Uso Comuni

  • Autenticazione utente e gestione dello stato di accesso
  • Memorizzazione temporanea dei dati del modulo
  • Archiviazione delle impostazioni delle preferenze dell'utente

Codice di Esempio

main.rs
Cargo.toml
use salvo::prelude::*;
use salvo::session::{CookieStore, Session, SessionDepotExt, SessionHandler};

#[tokio::main]
async fn main() {
    tracing_subscriber::fmt().init();
    let session_handler = SessionHandler::builder(
        CookieStore::new(),
        b"secretabsecretabsecretabsecretabsecretabsecretabsecretabsecretab",
    )
    .build()
    .unwrap();
    let router = Router::new()
        .hoop(session_handler)
        .get(home)
        .push(Router::with_path("login").get(login).post(login))
        .push(Router::with_path("logout").get(logout));

    let acceptor = TcpListener::new("0.0.0.0:8698").bind().await;
    Server::new(acceptor).serve(router).await;
}

#[handler]
pub async fn login(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    if req.method() == salvo::http::Method::POST {
        let mut session = Session::new();
        session
            .insert("username", req.form::<String>("username").await.unwrap())
            .unwrap();
        depot.set_session(session);
        res.render(Redirect::other("/"));
    } else {
        res.render(Text::Html(LOGIN_HTML));
    }
}

#[handler]
pub async fn logout(depot: &mut Depot, res: &mut Response) {
    if let Some(session) = depot.session_mut() {
        session.remove("username");
    }
    res.render(Redirect::other("/"));
}

#[handler]
pub async fn home(depot: &mut Depot, res: &mut Response) {
    let mut content = r#"<a href="login">Login</h1>"#.into();
    if let Some(session) = depot.session_mut()
        && let Some(username) = session.get::<String>("username")
    {
        content = format!(r#"Hello, {username}. <br><a href="logout">Logout</h1>"#);
    }
    res.render(Text::Html(content));
}

static LOGIN_HTML: &str = r#"<!DOCTYPE html>
<html>
    <head>
        <title>Login</title>
    </head>
    <body>
        <form action="/login" method="post">
            <h1>Login</h1>
            <input type="text" name="username" />
            <button type="submit" id="submit">Submit</button>
        </form>
    </body>
</html>
"#;