Rust + Axum + Shuttle:零运维部署 REST API 完整指南
        
        作者:API传播员 · 2025-11-03 · 阅读时间:6分钟
    
    
    
          
     
    
        
        本文详细介绍了如何使用Rust语言结合Axum框架和Shuttle平台构建REST API服务。教程包含从项目初始化、数据库集成(PostgreSQL/SQLx)、路由处理到最终部署的完整流程,提供了CRUD操作、请求参数处理和防SQL注入等实用代码示例,适合想学习Rust后端开发的开发者。
    
    
        
                
                文章目录
            
			 
        
一、为什么选择 Shuttle + Axum?
- 零运维:
cargo shuttle deploy自动构建、容器化、上线 - Rust 原生:Axum 类型安全、异步高性能
 - 内置数据库:PostgreSQL 连接池一行注解即可拥有
 - 成本友好:免费 tier 足够开发/演示,按量付费
 
💡 AI 助攻
想自动生成带注释的Cargo.toml?用「代码生成」提示词,30 秒即可拿到模板,再交给「代码优化」砍掉冗余特性,编译速度提升 20%!
二、技术栈与版本
| 组件 | 用途 | 版本 | 
|---|---|---|
| shuttle-service | 零运维部署平台 | 0.46.x | 
| axum | Web 框架 | 0.7.x | 
| sqlx | 异步 PostgreSQL 驱动 | 0.7.x | 
| serde | JSON 序列化 | 1.0 | 
| tokio | 异步运行时 | 1.x | 
三、项目初始化与结构
# 安装 Shuttle CLI
cargo install cargo-shuttle
# 创建项目
cargo shuttle init --name shuttle-example-axum
cd shuttle-example-axum
骨架:
src/
├── main.rs      # 入口 + 路由
├── db.rs        # 数据库连接
├── models.rs    # 实体与 JSON
└── migrations.sql # 建表脚本
四、数据库与迁移:一行注解搞定
① 注解获取连接池
use shuttle_shared_db::Postgres;
use sqlx::PgPool;
#[shuttle_runtime::main]
async fn axum(
    #[Postgres] pool: PgPool,   // ← 自动注入
) -> shuttle_axum::ShuttleAxum {
    // 运行迁移
    sqlx::migrate!()
        .run(&pool)
        .await
        .expect("migrate failed");
    let state = AppState { db: pool };
    Ok(router(state).into())
}
② 迁移文件 migrations.sql
CREATE TABLE IF NOT EXISTS records (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    email TEXT NOT NULL
);
🔍 AI 审查
把「SQL 注入风险」提交评审?「代码审查助手」可自动检查参数绑定、拼接语句,提前发现 80% 潜在 Bug!
五、模型与 JSON:自动映射
// src/models.rs
use serde::{Deserialize, Serialize};
use sqlx::FromRow;
#[derive(Debug, Serialize, Deserialize, FromRow)]
pub struct Record {
    pub id: i32,
    pub name: String,
    pub email: String,
}
#[derive(Debug, Deserialize)]
pub struct CreateRecord {
    pub name: String,
    pub email: String,
}
#[derive(Debug, Deserialize)]
pub struct UpdateRecord {
    pub name: Option<String>,
    pub email: Option<String>,
}
六、路由与业务逻辑
① 共享状态
// src/main.rs
use axum::{
    extract::{Path, State, Json},
    http::StatusCode,
    response::IntoResponse,
    routing::{get, post, put, delete},
    Router,
};
use sqlx::PgPool;
#[derive(Clone)]
struct AppState {
    db: PgPool,
}
async fn create_record(
    State(state): State<AppState>,
    Json(payload): Json<CreateRecord>,
) -> impl IntoResponse {
    let rec = sqlx::query_as!(
        Record,
        "INSERT INTO records (name, email) VALUES ($1, $2) RETURNING *",
        payload.name, payload.email
    )
    .fetch_one(&state.db)
    .await
    .unwrap();
    (StatusCode::CREATED, Json(rec))
}
② 动态路径与参数绑定
async fn get_record_by_id(
    State(state): State<AppState>,
    Path(id): Path<i32>,
) -> impl IntoResponse {
    let rec = sqlx::query_as!(
        Record,
        "SELECT * FROM records WHERE id = $1",
        id
    )
    .fetch_optional(&state.db)
    .await
    .unwrap();
    match rec {
        Some(r) => (StatusCode::OK, Json(r)),
        None => (StatusCode::NOT_FOUND, Json("")),
    }
}
③ 部分更新(PATCH)
async fn update_record(
    State(state): State<AppState>,
    Path(id): Path<i32>,
    Json(payload): Json<UpdateRecord>,
) -> impl IntoResponse {
    // 动态构建 SET 子句
    let mut sql = String::from("UPDATE records SET ");
    let mut args: Vec<String> = vec![];
    if let Some(name) = payload.name {
        sql.push_str("name = $1,");
        args.push(name);
    }
    if let Some(email) = payload.email {
        sql.push_str("email = $2,");
        args.push(email);
    }
    sql.truncate(sql.len() - 1); // 去掉末尾逗号
    sql.push_str(" WHERE id = $3 RETURNING *");
    let rec = sqlx::query_as::<_, Record>(&sql)
        .bind(args.get(0).unwrap_or(&"".to_string()))
        .bind(args.get(1).unwrap_or(&"".to_string()))
        .bind(id)
        .fetch_one(&state.db)
        .await
        .unwrap();
    (StatusCode::OK, Json(rec))
}
✅ AI 补救
把「动态 SQL 拼接」写进注释太麻烦?用「代码文档生成器」提示词,自动在函数头部生成标准注释,提醒后续接入sqlx-query-builder,文档一键达标!
七、路由汇总
fn router(state: AppState) -> Router {
    Router::new()
        .route("/records", post(create_record).get(list_records))
        .route("/records/:id", get(get_record_by_id).put(update_record).delete(delete_record))
        .with_state(state)
}
八、部署与测试
① 本地运行
cargo shuttle run
# 默认端口 8000
② 一键部署
cargo shuttle deploy --allow-dirty
# 自动生成域名:https://shuttle-example-axum.shuttleapp.rs
③ 快速验证
# 新增
curl -X POST https://<your-domain>.shuttleapp.rs/records \
  -H "Content-Type: application/json" \
  -d '{"name":"Alice","email":"alice@example.com"}'
# 查询
curl https://<your-domain>.shuttleapp.rs/records/1
九、扩展方向
| 方向 | 工具/库 | 
|---|---|
| 自定义错误 | thiserror + axum::response::IntoResponse | 
| 测试 | testcontainers + axum-test-helper | 
| 分页 | sqlx-query-builder + limit/offset | 
| JWT 认证 | jsonwebtoken + axum-extra | 
| OpenAPI | utoipa + swagger-ui | 
十、总结与下一步
通过本教程,你已掌握:
- Shuttle 零运维部署流程
 - Axum 异步路由与状态共享
 - SQLx 编译时安全查询
 - 动态 SQL 构建与错误处理
 
下一步可添加认证、分页、OpenAPI 文档等功能,打造生产级后端。祝编码愉快!
今晚就 push 到 GitHub,明天就能用 Shuttle 一键上线!🚀
原文链接: https://www.shuttle.dev/blog/2024/01/31/write-a-rest-api-rust
热门推荐
        一个账号试用1000+ API
            助力AI无缝链接物理世界 · 无需多次注册
            
        3000+提示词助力AI大模型
            和专业工程师共享工作效率翻倍的秘密
            
        热门API
- 1. AI文本生成
 - 2. AI图片生成_文生图
 - 3. AI图片生成_图生图
 - 4. AI图像编辑
 - 5. AI视频生成_文生视频
 - 6. AI视频生成_图生视频
 - 7. AI语音合成_文生语音
 - 8. AI文本生成(中国)
 
最新文章
- API协议设计的10种技术
 - ComfyUI API是什么:深入探索ComfyUI的API接口与应用
 - 从架构设计侧剖析: MCP vs A2A 是朋友还是对手?
 - Kimi Chat API入门指南:从注册到实现智能对话
 - 免费查询公司注册信息API的使用指南
 - 防御 API 攻击:保护您的 API 和数据的策略
 - 香港支付宝实名认证:是什么?怎么用?
 - 如何获取 Coze开放平台 API 密钥(分步指南)
 - 如何保护您的API免受自动化机器人和攻击 | Zuplo博客
 - ASP.NET Core Minimal APIs 入门指南 – JetBrains 博客
 - 什么是 OpenReview
 - Vue中使用echarts@4.x中国地图及AMap相关API的使用