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大模型
和专业工程师共享工作效率翻倍的秘密
最新文章
- 如何获取ANTHROPIC 开放平台 API Key 密钥(分步指南)
- 使用人工智能测试工具构建更好的API
- 了解异步API
- One-API实现大语言模型请求接口的统一
- API Key 密钥与API 令牌:有什么区别?
- 营业执照OCR识别API在Java、Python、PHP中的使用教程
- OpenAI OSS API 架构深度解析:GPT-OSS-120B 与 GPT-OSS-20B 多模型接入全指南
- 如何在Python中使用免费的DeepL翻译API
- API 提示词 vs Agent 提示词:一篇文章讲清楚本质区别
- 2025年适合您项目的API框架类型 – Aloa
- 使用缓存策略提高 API 性能
- 什么是API加密?