# Rust Blog Backend 基于 **Rust + Actix-web + SQLite** 的博客后端 API 服务。 ## 特性 - 用户注册/登录 (JWT 认证) - 博客文章 CRUD (创建、读取、更新、软删除) - 图片上传 (支持 jpg/png/webp,含文件类型校验) - 分页查询 - 请求限流 (Rate Limiting) - SQLite 数据库 (WAL 模式,高性能) ## 项目结构 ``` blog_backend/ ├── .env # 环境配置 (不提交到 Git) ├── .env.example # 配置模板 ├── Cargo.toml # 依赖清单 ├── migrations/ # 数据库迁移文件 ├── uploads/ # 上传文件存储目录 ├── postman_collection.json # Postman 测试集合 └── src/ ├── main.rs # 入口:HTTP 服务器启动 ├── config.rs # 配置加载 ├── db.rs # 数据库连接池 ├── error.rs # 统一错误处理 ├── models/ # 数据模型 (User, Post) ├── dtos/ # 请求/响应结构体 ├── repository/ # 数据库操作层 ├── handlers/ # API 控制器 ├── middleware/ # JWT 中间件 └── utils/ # 工具函数 (密码哈希、JWT) ``` ## 快速开始 ### 1. 环境要求 - Rust 1.70+ - SQLite 3 ### 2. 安装依赖 ```bash # 安装 sqlx-cli (可选,用于数据库迁移管理) cargo install sqlx-cli --no-default-features --features sqlite ``` ### 3. 配置环境变量 ```bash cp .env.example .env ``` 编辑 `.env` 文件: ```env DATABASE_URL=sqlite:./blog.db JWT_SECRET=你的密钥至少32个字符 BIND_ADDR=127.0.0.1:8080 RUST_LOG=debug ``` ### 4. 运行 ```bash # 开发模式 cargo run # 生产构建 cargo build --release strip target/release/blog_backend # 可选:减小体积 ./target/release/blog_backend ``` ## API 接口 ### 认证 | 方法 | 路径 | 说明 | 认证 | |------|------|------|------| | POST | `/api/auth/register` | 用户注册 | 否 | | POST | `/api/auth/login` | 用户登录 | 否 | **注册/登录请求:** ```json { "email": "user@example.com", "password": "password123" } ``` **响应:** ```json { "token": "eyJhbGciOiJIUzI1NiIs...", "user": { "id": "uuid", "email": "user@example.com" } } ``` ### 文章 | 方法 | 路径 | 说明 | 认证 | |------|------|------|------| | GET | `/api/posts` | 获取文章列表 (分页) | 否 | | GET | `/api/posts/:id` | 获取单篇文章 | 否 | | POST | `/api/posts` | 创建文章 | 是 | | PUT | `/api/posts/:id` | 更新文章 | 是 | | DELETE | `/api/posts/:id` | 删除文章 (软删除) | 是 | **分页参数:** ``` GET /api/posts?page=1&limit=10 ``` **创建文章请求:** ```json { "title": "文章标题", "content": "文章内容", "published": true } ``` **分页响应:** ```json { "data": [...], "page": 1, "limit": 10, "total": 100, "total_pages": 10 } ``` ### 文件上传 | 方法 | 路径 | 说明 | 认证 | |------|------|------|------| | POST | `/api/upload` | 上传图片 | 是 | **请求:** `multipart/form-data`,字段名 `file` **限制:** - 支持格式:jpg, jpeg, png, webp - 最大大小:5MB - 包含 Magic Number 校验防止伪装文件 **响应:** ```json { "filename": "uuid.jpg", "url": "/uploads/uuid.jpg" } ``` ### 静态文件 | 路径 | 说明 | |------|------| | `/uploads/*` | 访问上传的文件 | ## 认证说明 需要认证的接口,请在请求头中添加: ``` Authorization: Bearer ``` ## 限流规则 | 接口类型 | 限制 | |----------|------| | 全局 | 60 请求/分钟 | | 认证接口 | 5 请求/分钟 | | 上传接口 | 5 请求/分钟 | ## 部署 ### 1. 构建发布版本 ```bash cargo build --release strip target/release/blog_backend ``` ### 2. 复制文件到服务器 ```bash scp target/release/blog_backend user@server:/opt/blog/ scp .env.example user@server:/opt/blog/.env scp -r migrations/ user@server:/opt/blog/ ``` ### 3. 服务器配置 ```bash # 创建目录 mkdir -p /opt/blog/uploads # 编辑配置 vim /opt/blog/.env ``` 生产环境 `.env`: ```env DATABASE_URL=sqlite:./blog.db JWT_SECRET=生产环境强密钥至少32字符 BIND_ADDR=0.0.0.0:8080 RUST_LOG=warn ``` ### 4. Systemd 服务 创建 `/etc/systemd/system/blog.service`: ```ini [Unit] Description=Rust Blog Backend After=network.target [Service] Type=simple User=www-data WorkingDirectory=/opt/blog ExecStart=/opt/blog/blog_backend Restart=always RestartSec=5 Environment=RUST_LOG=warn [Install] WantedBy=multi-user.target ``` 启动服务: ```bash sudo systemctl daemon-reload sudo systemctl enable blog sudo systemctl start blog sudo systemctl status blog ``` ### 5. Nginx 反向代理 (可选) ```nginx server { listen 80; server_name blog.example.com; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /uploads { alias /opt/blog/uploads; expires 30d; } } ``` ## 测试 导入 `postman_collection.json` 到 Postman 进行 API 测试。 测试流程: 1. 运行 **Register** 或 **Login** (自动保存 Token) 2. 运行 **Create Post** (自动保存 Post ID) 3. 测试其他接口 ## 技术栈 | 组件 | 技术 | |------|------| | Web 框架 | Actix-web 4 | | 数据库 | SQLite + SQLx | | 认证 | JWT (jsonwebtoken) | | 密码哈希 | Argon2 | | 限流 | actix-governor | | 日志 | tracing | ## License MIT