Session

Middleware fournissant la prise en charge des Sessions.

Qu'est-ce qu'une Session

Une Session fait référence aux données utilisateur stockées côté serveur, généralement utilisées pour suivre l'état de l'utilisateur et stocker des données temporaires. Dans les applications web, la Session résout le caractère sans état du protocole HTTP, permettant au serveur de reconnaître plusieurs requêtes provenant du même utilisateur.

Utilisation des Sessions dans Salvo

Dans Salvo, le middleware Session offre une API simple pour lire et écrire les données de session. Le SessionDepot peut être utilisé pour obtenir une instance de session, tandis que des méthodes telles que get, set et remove permettent de gérer les données de session.

Cas d'utilisation courants

  • Authentification des utilisateurs et gestion de l'état de connexion
  • Stockage temporaire des données de formulaire
  • Stockage des préférences de l'utilisateur

Exemple de code

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>
"#;