要使用 Axum session 构建 Rust 应用,第一步是选择你的服务器。 在本例中,我们将使用 loco :)
首先,创建一个新项目并选择 SaaS app
模板:
$ cargo install loco
$ 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 session crate 添加到 Cargo.toml:
axum_session = {version = "0.10.1", default-features = false}
然后,将 Axum session layer 添加到你的路由器。打开 app.rs 并添加以下钩子:
pub struct App;
#[async_trait]
impl Hooks for App {
fn app_name() -> &'static str {
env!("CARGO_CRATE_NAME")
}
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)
}
}
现在,你可以创建使用 Axum session 的控制器。使用 cargo loco generate controller
命令:
❯ cargo loco generate controller mysession --api
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:5150/mysession
端点来查看会话。
创建带数据库加密的会话
要添加会话数据库加密,请在 Cargo.toml 中包含 Axum session crate 和带有 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 session 所期望的 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 session layer 添加到 app.rs
中的路由器:
use session; pub struct App;
#[async_trait]
impl Hooks for App {
fn app_name() -> &'static str {
env!("CARGO_CRATE_NAME")
}
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)
}
}
像之前一样使用 cargo loco generate controller
创建控制器
❯ cargo loco generate controller mysession --api
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:5150/mysession
端点将显示会话。