使用 Axum Session 构建 Rust 应用


要使用Axum session构建 Rust 应用程序,第一步是选择您的服务器。在这种情况下,我们将使用loco  :)

首先创建一个新项目并选择Saas app模板:

$ cargo install loco-cli
$ loco new
 App name? · myapp
 What would you like to build? ›
  lightweight-service (minimal, only controllers and views)
  Rest API (with DB and user auth)
 Saas app (with DB and user auth)

基于内存存储创建会话
首先,将 Axum 会话箱添加到 Cargo.toml 中:

axum_session = {version = "0.10.1", default-features = false}

然后,将 Axum 会话层添加到您的路由器。打开 app.rs 并添加以下钩子:

pub struct App;
#[async_trait]
impl Hooks for App {
    fn app_name() -> &'static str {
        env!("CARGO_CRATE_NAME")
    }

   
// Other hooks...
    async fn after_routes(router: AxumRouter, _ctx: &AppContext) -> Result<AxumRouter> {
        let session_config =
            axum_session::SessionConfig::default().with_table_name(
"sessions_table");

        let session_store =
            axum_session::SessionStore::<axum_session::SessionNullPool>::new(None, session_config)
                .await
                .unwrap();

        let router = router.layer(axum_session::SessionLayer::new(session_store));
        Ok(router)
    }
   
// Other hooks...
}

现在,您可以创建使用 Axum 会话的控制器。使用cargo loco generate controller命令:

❯ cargo loco generate controller mysession
    Finished dev [unoptimized + debuginfo] target(s) in 0.36s
     Running `target/debug/axum-session-cli generate controller mysession`
added: "src/controllers/mysession.rs"
injected:
"src/controllers/mod.rs"
injected:
"src/app.rs"
added:
"tests/requests/mysession.rs"
injected:
"tests/requests/mod.rs"

打开src/controllers/mysession.rs控制器生成器创建的文件并将其内容替换为以下代码:

#![allow(clippy::unused_async)]
use axum_session::{Session, SessionNullPool};
use loco_rs::prelude::*;

pub async fn get_session(session: Session<SessionNullPool>) -> Result<()> {
    println!("{:#?}", session);
    format::empty()
}

pub fn routes() -> Routes {
    Routes::new().prefix(
"mysession").add("/", get(get_session))
}

现在,您可以调用http://127.0.0.1:3000/api/mysession端点来查看会话。

基于数据库加密创建会话
要添加会话数据库加密,请在 Cargo.toml 中包含 Axum 会话箱和带有 SQLx 的 PostgreSQL:

axum_session = {version = "0.10.1"}
sqlx = { version =
"0.7.2", features = [
 
"macros",
 
"postgres",
 
"_unstable-all-types",
 
"tls-rustls",
 
"runtime-tokio",
] }

创建一个session.rs包含以下内容的文件:connect_to_database获取Database配置并返回 axum 会话期望的 PgPool 实例。

use sqlx::postgres::PgPool;
use loco_rs::{
    config::Database,
    errors::Error,
    Result,
};

async fn connect_to_database(config: &Database) -> Result<PgPool> {
    PgPool::connect(&config.uri)
        .await
        .map_err(|e| Error::Any(e.into()))
}

将 Axum 会话层添加到您的路由器app.rs:

use session; // This is the session.rs file
pub struct App;
#[async_trait]
impl Hooks for App {
    fn app_name() -> &'static str {
        env!(
"CARGO_CRATE_NAME")
    }

   
// Other hooks...
    async fn after_routes(router: AxumRouter, ctx: &AppContext) -> Result<AxumRouter> {
        let conn = session.connect_to_database(&ctx.config.database).await?;
        let session_config = axum_session::SessionConfig::default()
            .with_table_name(
"sessions_table")
            .with_key(axum_session::Key::generate())
            .with_database_key(axum_session::Key::generate())
            .with_security_mode(axum_session::SecurityMode::PerSession);

        let session_store = axum_session::SessionStore::<axum_session::SessionPgPool>::new(
            Some(conn.clone().into()),
            session_config,
        )
        .await
        .unwrap();

        let router = router.layer(axum_session::SessionLayer::new(session_store));
        Ok(router)
    }
   
// Other hooks...
}

像之前一样创建控制器cargo loco generate controller

❯ cargo loco generate controller mysession
    Finished dev [unoptimized + debuginfo] target(s) in 0.36s
     Running `target/debug/axum-session-cli generate controller mysession`
added: "src/controllers/mysession.rs"
injected:
"src/controllers/mod.rs"
injected:
"src/app.rs"
added:
"tests/requests/mysession.rs"
injected:
"tests/requests/mod.rs"

并将 的内容替换src/controllers/mysession.rs为提供的代码。

#![allow(clippy::unused_async)]
use axum_session::{Session, SessionPgPool};
use loco_rs::prelude::*;

pub async fn get_session(session: Session<SessionPgPool>) -> Result<()> {
    println!("{:#?}", session);
    format::empty()
}

pub fn routes() -> Routes {
    Routes::new().prefix(
"mysession").add("/", get(get_session))
}

现在,调用http://127.0.0.1:3000/api/mysession端点将显示会话。