Rust REST API 进阶:查询参数、业务解耦与虚拟数据返回全程指南

作者:API传播员 · 2025-11-02 · 阅读时间:5分钟
本文详细介绍了如何使用Rust和Actix Web框架为REST API添加第二个端点,该端点能够处理查询参数并返回虚拟的纽约市出租车数据。文章重点讲解了如何解耦处理逻辑、实现get_fake_trips函数以及处理错误,展示了Rust强类型系统在API开发中的优势。

一、背景与目标

在这篇文章中,我们将继续完善一个用 Rust 构建的简单 REST API。之前的 API 仅包含一个健康检查端点,用于返回“我还活着”的消息。今天,我们将逐步添加一个新的端点,该端点将返回历史的纽约市出租车数据。为了简化实现,我们将返回虚拟数据。


二、实现步骤总览

步骤 目标 关键实现
① 查询参数解析 提取 from_msn_results Actix Web 自动解析
② 业务逻辑解耦 保持 handler 简洁 新建 backend.rs
③ 虚拟数据生成 返回 Vec<Trip> get_fake_trips()
④ 错误处理 Result 类型 + match HTTP 200 vs 500

三、查询参数解析:Actix Web 自动提取

请求示例:

GET /trips?from_ms=1714204800000&n_results=100

Handler 签名:

async fn trips(Query(params): Query<TripRequest>) -> impl Responder {
    // params.from_ms / params.n_results 即用
}

定义请求体:

use serde::Deserialize;

#[derive(Deserialize)]
struct TripRequest {
    from_ms: u64,
    n_results: usize,
}

💡 AI 助攻
想自动生成「查询参数校验」代码?用「代码生成」提示词,30 秒即可拿到 serde + validator 模板,再交给「代码优化」砍掉冗余克隆,性能提升 40%!


四、业务解耦:新建 backend.rs

1. 目录结构

src/
├── main.rs
└── backend.rs // 新增

2. 公开函数签名

// backend.rs
use chrono::{DateTime, Utc};

#[derive(Serialize)]
pub struct Trip {
    pub id: u32,
    pub pickup_time: DateTime<Utc>,
    pub distance: f32, // 英里
}

pub fn get_fake_trips(from_ms: u64, n_results: usize) -> Result<Vec<Trip>, String> {
    if n_results == 0 {
        return Err("n_results must be > 0".to_string());
    }
    let base_time = DateTime::from_utc(
        NaiveDateTime::from_timestamp_opt((from_ms / 1000) as i64, 0).unwrap(),
        Utc,
    );
    let mut trips = Vec::with_capacity(n_results);
    for i in 0..n_results {
        trips.push(Trip {
            id: i as u32,
            pickup_time: base_time + Duration::minutes(i as i64),
            distance: 1.0 + (i as f32) * 0.1,
        });
    }
    Ok(trips)
}

🔍 AI 审查
把「虚拟数据生成逻辑」提交评审?「代码审查助手」可自动检查边界条件、空 Vec 处理,提前发现 80% 潜在 Bug!


五、错误处理:Result 类型 + match 表达式

main.rs 中调用:

use crate::backend::{get_fake_trips, Trip};

async fn trips_handler(Query(req): Query<TripRequest>) -> impl Responder {
    match get_fake_trips(req.from_ms, req.n_results) {
        Ok(trips) => (StatusCode::OK, Json(trips)),
        Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": e}))),
    }
}
  • Ok(trips) → HTTP 200 + JSON 数组
  • Err(e) → HTTP 500 + 错误消息

六、快速测试

启动服务器:

cargo run

发起请求:

curl -X GET "http://localhost:8080/trips?from_ms=1714204800000&n_results=5"

预期返回(简化):

[
  {"id":0,"pickup_time":"2024-04-27T00:00:00Z","distance":1.0},
  {"id":1,"pickup_time":"2024-04-27T00:01:00Z","distance":1.1},
  ...
]

七、进阶路线图

阶段 技术点 工具/库
① 真实数据 连接 PostgreSQL sqlx + 迁移
② 分页 limit+offset 查询 serde_qs
③ 认证 JWT 校验 actix-jwt
④ 日志 结构化日志 tracing
⑤ 容器化 多阶段构建 Docker

AI 补救
把「Dockerfile 多阶段构建」写进注释太麻烦?用「代码文档生成器」提示词,自动在文件头部生成标准注释,提醒后续接入缓存挂载,文档一键达标!


八、总结与下一步

通过以上步骤,我们成功为 Rust 构建的 REST API 添加了一个新的端点。这个端点能够解析查询参数并返回虚拟的纽约市出租车行程数据。虽然我们目前返回的是虚拟数据,但这一实现为后续集成真实数据奠定了基础。Rust 的强类型系统和编译器强制的隐私机制,使得代码更加安全和可靠。通过解耦逻辑,我们也提高了代码的可维护性。

下周将继续探讨如何集成真实数据库与分页功能,敬请期待!🚀


原文链接: https://www.realworldml.net/blog/let-s-rust