rust-fullstack

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Rust Full-Stack Web Development Patterns

Rust全栈Web开发模式

Tech Stack

技术栈

LayerTech
FrontendLeptos (Rust→WASM CSR), Tailwind CSS + DaisyUI
BackendAxum, SQLx (compile-time checked queries)
DatabasePostgreSQL
BuildTrunk (WASM), Docker, Makefile
层级技术
前端Leptos(Rust→WASM CSR)、Tailwind CSS + DaisyUI
后端Axum、SQLx(编译时校验查询)
数据库PostgreSQL
构建Trunk(WASM)、Docker、Makefile

JWT Dual-Token Auth

JWT双令牌认证

Access Token (short-lived)  → API request auth
Refresh Token (long-lived)  → Access token renewal
  • Store in HTTP-only Cookie (XSS protection)
  • Backend: Token validation
  • Frontend: Auto-retry on 401
rust
// Backend: Cookie setup
let cookie = format!(
    "access_token={}; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age={}",
    token, 900  // 15 min
);

// Frontend: 401 retry
if response.status() == 401 {
    refresh_token().await?;
    // Retry original request
}
Access Token(短有效期) → API请求认证
Refresh Token(长有效期) → Access Token续期
  • 存储在HttpOnly Cookie中(防止XSS攻击)
  • 后端:令牌校验
  • 前端:401状态码自动重试
rust
// 后端:Cookie配置
let cookie = format!(
    "access_token={}; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age={}",
    token, 900  // 15分钟
);

// 前端:401重试
if response.status() == 401 {
    refresh_token().await?;
    // 重试原请求
}

Frontend State Management

前端状态管理

rust
provide_context(AuthContext::new());
provide_context(AppCache::new());  // TTL-based cache
provide_context(ToastContext::new());

// localStorage for preferences
let stored = window().local_storage()?.get_item("preferences")?;
rust
provide_context(AuthContext::new());
provide_context(AppCache::new());  // 基于TTL的缓存
provide_context(ToastContext::new());

// localStorage存储偏好设置
let stored = window().local_storage()?.get_item("preferences")?;

API Client Pattern

API客户端模式

rust
// Rate limiting (429) handling
async fn fetch_with_retry<T>(request: impl Fn() -> Future<T>) -> Result<T> {
    loop {
        match request().await {
            Err(e) if e.status() == 429 => {
                let delay = e.retry_after().unwrap_or(1000);
                sleep(delay).await;
            }
            result => return result,
        }
    }
}

// Token refresh queue (prevent multiple refreshes)
static REFRESH_LOCK: OnceCell<RwLock<()>> = OnceCell::new();
rust
// 限流(429)处理
async fn fetch_with_retry<T>(request: impl Fn() -> Future<T>) -> Result<T> {
    loop {
        match request().await {
            Err(e) if e.status() == 429 => {
                let delay = e.retry_after().unwrap_or(1000);
                sleep(delay).await;
            }
            result => return result,
        }
    }
}

// 令牌刷新队列(防止重复刷新)
static REFRESH_LOCK: OnceCell<RwLock<()>> = OnceCell::new();

Multi-tenant Routing

多租户路由

{tenant}.example.com → Tenant identification
rust
fn extract_subdomain(host: &str) -> Option<String> {
    let parts: Vec<&str> = host.split('.').collect();
    (parts.len() >= 3).then(|| parts[0].to_string())
}

async fn check_tenant_access(claims: &Claims, subdomain: &str) -> Result<(), AppError> {
    // Verify user has access to this tenant
}
{tenant}.example.com → 租户识别
rust
fn extract_subdomain(host: &str) -> Option<String> {
    let parts: Vec<&str> = host.split('.').collect();
    (parts.len() >= 3).then(|| parts[0].to_string())
}

async fn check_tenant_access(claims: &Claims, subdomain: &str) -> Result<(), AppError> {
    // 验证用户是否有权限访问该租户
}

Database

数据库

rust
// SQLx compile-time query checking
let user = sqlx::query_as!(
    User,
    r#"SELECT id, name, role as "role: UserRole" FROM users WHERE id = $1"#,
    id
).fetch_one(&pool).await?;

// PostgreSQL ENUMs
#[derive(sqlx::Type)]
#[sqlx(type_name = "user_role", rename_all = "PascalCase")]
pub enum UserRole { Admin, AreaManager, ServiceStation }
rust
// SQLx编译时查询校验
let user = sqlx::query_as!(
    User,
    r#"SELECT id, name, role as "role: UserRole" FROM users WHERE id = $1"#,
    id
).fetch_one(&pool).await?;

// PostgreSQL枚举类型
#[derive(sqlx::Type)]
#[sqlx(type_name = "user_role", rename_all = "PascalCase")]
pub enum UserRole { Admin, AreaManager, ServiceStation }

Common Commands

常用命令

sh
make dev          # Start local environment
make fmt          # Format (cargo fmt + leptosfmt)
make lint         # Clippy checks
make test         # Run tests
make migrate-run  # Apply migrations
sh
make dev          # 启动本地环境
make fmt          # 格式化代码(cargo fmt + leptosfmt)
make lint         # Clippy检查
make test         # 运行测试
make migrate-run  # 执行数据库迁移

Dev Notes

开发说明

ItemValue
Backend port3000
Local subdomain
lvh.me
(resolves to 127.0.0.1)
Env files
.env.development
,
.env.staging
,
.env.production
Required env
DATABASE_URL
,
JWT_SECRET
,
APP_ENV
后端端口3000
本地子域名
lvh.me
(解析到127.0.0.1)
环境文件
.env.development
,
.env.staging
,
.env.production
必填环境变量
DATABASE_URL
,
JWT_SECRET
,
APP_ENV

Related Skills

相关技能

  • leptos-guide
    - Leptos frontend
  • axum-guide
    - Axum backend
  • sqlx-postgres
    - SQLx + PostgreSQL
  • leptos-guide
    - Leptos前端开发
  • axum-guide
    - Axum后端开发
  • sqlx-postgres
    - SQLx + PostgreSQL