rust-fullstack
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRust Full-Stack Web Development Patterns
Rust全栈Web开发模式
Tech Stack
技术栈
| Layer | Tech |
|---|---|
| Frontend | Leptos (Rust→WASM CSR), Tailwind CSS + DaisyUI |
| Backend | Axum, SQLx (compile-time checked queries) |
| Database | PostgreSQL |
| Build | Trunk (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 identificationrust
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 migrationssh
make dev # 启动本地环境
make fmt # 格式化代码(cargo fmt + leptosfmt)
make lint # Clippy检查
make test # 运行测试
make migrate-run # 执行数据库迁移Dev Notes
开发说明
| Item | Value |
|---|---|
| Backend port | 3000 |
| Local subdomain | |
| Env files | |
| Required env | |
| 项 | 值 |
|---|---|
| 后端端口 | 3000 |
| 本地子域名 | |
| 环境文件 | |
| 必填环境变量 | |
Related Skills
相关技能
- - Leptos frontend
leptos-guide - - Axum backend
axum-guide - - SQLx + PostgreSQL
sqlx-postgres
- - Leptos前端开发
leptos-guide - - Axum后端开发
axum-guide - - SQLx + PostgreSQL
sqlx-postgres