Sesión

Middleware que proporciona soporte para Sesión.

¿Qué es una Sesión?

Una sesión se refiere a los datos del usuario almacenados en el lado del servidor, utilizados comúnmente para rastrear el estado del usuario y almacenar datos temporales. En aplicaciones web, la sesión aborda la naturaleza sin estado del protocolo HTTP, permitiendo que el servidor reconozca múltiples solicitudes del mismo usuario.

Uso de Sesión en Salvo

En Salvo, el middleware de Sesión ofrece una API simple para leer y escribir datos de sesión. Se puede utilizar SessionDepot para obtener una instancia de sesión, mientras que métodos como get, set y remove permiten gestionar los datos de sesión.

Casos de Uso Comunes

  • Autenticación de usuarios y gestión del estado de inicio de sesión
  • Almacenamiento temporal de datos de formularios
  • Almacenamiento de configuraciones de preferencias del usuario

Código de Ejemplo

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