セッション

Sessionをサポートするミドルウェアを提供します。

セッションとは

セッションはサーバー側に保存されるユーザーデータの一時的な領域で、通常ユーザー状態の追跡や一時データの保存に使用されます。Webアプリケーションにおいて、セッションはHTTPプロトコルのステートレス性を解決し、サーバーが同一ユーザーからの複数リクエストを識別できるようにします。

Salvoにおけるセッションの利用

Salvoでは、セッションミドルウェアがセッションデータの読み書きを行うシンプルなAPIを提供しています。SessionDepotを通じてセッションインスタンスを取得し、getsetremoveなどのメソッドでセッションデータを管理できます。

主な用途

  • ユーザー認証とログイン状態管理
  • フォームデータの一時保存
  • ユーザー設定の保存

サンプルコード

main.rs
Cargo.toml
session-login/src/main.rs
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:5800").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() {
        if 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>
"#;