在前后端联调、设备端开发或接口回归测试中,我们经常需要一个稳定、可控的 HTTP 服务。真实后端尚未准备好时,先用固定 JSON 返回值把调用链跑通,是一种简单有效的办法。
这个项目使用 Rust 标准库实现了一个轻量级 Mock API 服务:不依赖 Axum、Actix 等 Web 框架,直接通过 TcpListener 接收 TCP 连接,手动解析 HTTP 请求,再根据方法和路径返回内置 JSON 文件或固定响应。
项目地址:
https://download.csdn.net/download/wy313622821/93309459
项目结构
rust-service-api/
├── Cargo.toml
├── assets/ # 可复用的 JSON 响应数据
│ ├── door_tag.json
│ ├── drug_detail.json
│ ├── drug_set_grid.json
│ ├── login.json
│ ├── project.json
│ └── user_id.json
└── src/
├── main.rs # TCP 监听、HTTP 请求读取和响应发送
├── router/
│ ├── mod.rs
│ ├── router_gcp.rs # 当前使用的路由表
│ └── router_sjg.rs # 另一套路由示例
└── shared/
└── mod.rs # 响应结构、资产读取和路径处理
项目依赖很少,主要使用 serde 和 serde_json。当前的响应数据以 JSON 文本形式返回,因此路由层不需要为每种业务对象定义 Rust 结构体。
启动服务
确保本机拥有 Rust 工具链后,在项目根目录执行:
cargo run
服务会绑定到 192.168.101.139:3000:
http://192.168.101.139:3000
这里使用的是固定局域网地址。如果本机网卡地址发生变化,或者其他设备无法访问,需要同步修改 src/main.rs 中的绑定地址,并检查 Windows 防火墙规则。只允许本机访问时,也可以改为 127.0.0.1:3000。
一次请求是怎样被处理的
入口函数 handle 展示了一个 HTTP 请求的最小处理流程:
- 从
TcpStream读取第一行,得到 HTTP 方法和路径。 - 继续读取请求头,提取
Content-Length。 - 根据长度读取请求体。
- 只接受
GET和POST,其他方法返回405 Method Not Allowed。 - 使用
extract_base_path去掉查询字符串,例如/api/UserRole?x=1会变成/api/UserRole。 - 将方法、基础路径和请求体交给路由模块。
- 通过
build_response统一拼装状态行、响应头和 JSON 响应体。
这个流程的优点是直观。我们可以清楚看到 HTTP 数据从网络进入程序,再流向路由和响应构造器的每一步;代价是需要自己处理协议细节。
调用示例
健康检查:
curl.exe "http://192.168.101.139:3000/"
登录接口:
curl.exe -X POST "http://192.168.101.139:3000/api/Login" `
-H "Content-Type: application/json" `
-d '{"user_code":"12","password":"12"}'
查询项目:
curl.exe -X POST "http://192.168.101.139:3000/api/Project/QueryProject" `
-H "Content-Type: application/json" `
-d '{}'
查询用户角色:
curl.exe "http://192.168.101.139:3000/api/UserRole?userId=2"
需要注意,当前路由匹配区分大小写,例如 /api/Login 和 /api/login 不是同一个地址。查询参数会被移除后再匹配,但请求体目前只负责读取和日志输出,尚未参与业务判断。
这个实现适合什么场景
它很适合以下场景:
- 前端需要快速获得稳定的接口响应。
- 硬件或客户端程序需要一个局域网内的测试服务。
- 联调时需要复现固定的项目、药物或用户数据。
- 想学习 TCP、HTTP 请求格式和 Rust 并发基础。
每个连接都会通过 thread::spawn 交给独立线程处理,因此多个客户端可以同时请求。对于低并发的内部测试服务,这种实现足够轻便,也便于调试。
当前实现的边界
“手写 HTTP”很适合学习和制作 Mock 服务,但不应直接当作生产级 HTTP 服务器。当前代码还有几个明确边界:
- 只解析请求行、
Content-Length和请求体,没有完整处理 chunked 编码、超时和异常连接。 - 每个请求处理完都关闭连接,不支持 keep-alive。
- 响应的
Content-Length按 Rust 字符串的字节长度计算时应使用 UTF-8 字节数;当前 JSON 响应主要来自文件,建议进一步统一为as_bytes().len()。 - 路由和响应内容是静态的,尚未校验 JSON 请求体,也没有真正的登录认证或数据持久化。
- 当前绑定地址写死在源码中,部署到其他机器前需要配置化。
下一步可以怎样演进
如果项目从 Mock 服务继续发展,可以按风险和收益逐步改进:
- 将监听地址和端口放入环境变量或配置文件。
- 使用
serde_json校验并读取请求体中的字段。 - 增加统一的
Content-Type、错误响应和日志格式。 - 为路由和
extract_base_path添加单元测试。 - 当路由、并发或协议需求变复杂时,迁移到 Axum 或 Actix Web。
总结
这个项目用很少的代码搭出了一个可运行的 HTTP Mock 服务:TcpListener 负责接收连接,handle 负责读取请求,路由模块负责决定响应,shared 模块负责复用响应构造和 JSON 资产读取。它不追求替代成熟 Web 框架,而是把一次 API 调用背后的关键步骤完整摊开,非常适合作为 Rust 网络编程和前后端联调的起点。

301

被折叠的 条评论
为什么被折叠?



