salvo rust解析请求数据的各种姿势

简介: salvo rust解析请求数据的各种姿势

最近使用rust web框架salvo练习rust,为了巩固学习成果,总结一下如何使用salvo解析请求数据。项目如何搭建,可以查看salvo搭建rust web项目。

也欢迎小伙伴来github上下载hello_salvo一起练习rust,觉得不错的话,给一个小星星哟!

GET请求

  • 从请求url中取参数
// "/user/<id>?oid={order_id}"
#[handler]
async fn query_order_in_user(req: &mut Request, res: &mut Response) {
    // 从路径上取参数
    let user_id = req.param::<String>("id").unwrap();
    // 从?后面取参数
    let order_id = req.query::<String>("oid").unwrap();
    // 写出响应数据
    res.render(format!("user_id:{}\norder_id:{}", user_id, order_id));
}
复制代码
  • 实体类接收
#[derive(Debug, Serialize, Deserialize, Extractible)]
struct OrderQuery {
    // 从请求路径中解析,别名是“id”
    #[extract(alias = "id", source(from = "param"))]
    user_id: String,
    // 从?后面解析,别名是“oid”
    #[extract(alias = "oid", source(from = "query"))]
    order_id: String,
}
// /user/<id>?oid={order_id}
#[handler]
async fn query_order_in_user(query: OrderQuery, res: &mut Response) {
    // 从路径上取参数
    let user_id = query.user_id;
    // 从?后面取参数
    let order_id = query.order_id;
    // 写出响应数据
    res.render(format!("user_id:{}\norder_id:{}", user_id, order_id));
}
复制代码
  • Router编写方式:
Router::with_path("/user/<id>").get(query_order_in_user)
复制代码

POST请求

先定义UserInfo结构体用来接收数据

#[derive(Debug, Serialize, Deserialize, Extractible)]
#[extract(
default_source(from = "body", format = "json")
)]
struct UserInfo {
    pub account: String,
    pub password: String,
}
复制代码
  • 从请求体中解析数据
#[handler]
async fn create_account(req: &mut Request) -> Result<String, GlobalError> {
    // 从请求体中解析参数并创建UserInfo对象
    let user_info: UserInfo = req.extract_body().await.unwrap();
    // 取出数据
    let account = &user_info.account;
    let password = &user_info.password;
    // 调用业务逻辑
    match AccountService::add_account(account, password) {
        Ok(x) => {
            info!("受影响的行数:{}", x);
            Ok(String::from("成功!"))
        }
        Err(e) => Err(e)
    }
}
复制代码
  • 实体类接收数据
// 自动从请求中取数据并实例化UserInfo对象
#[handler]
async fn create_account(user_info: UserInfo) -> Result<String, GlobalError> {
    let account = &user_info.account;
    let password = &user_info.password;
    match AccountService::add_account(account, password) {
        Ok(x) => {
            info!("受影响的行数:{}", x);
            Ok(String::from("成功!"))
        }
        Err(e) => Err(e)
    }
}
复制代码
  • Router的编写方式:
Router::with_path("/create_account").post(create_account)
复制代码
  • 发生请求的方式:
curl -X "POST" "http://127.0.0.1:7878/create_account" \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{
  "account": "helloworld",
  "password": "123456"
}'
复制代码
  • 同时从请求路径,url参数和请求体中取数据
#[derive(Debug, Serialize, Deserialize, Extractible)]
struct OrderSave {
    // 从请求路径中取参数"id"的值
    #[extract(alias = "id", source(from = "param"))]
    user_id: String,
    // 从?后面取参数"oid"的值
    #[extract(alias = "oid", source(from = "query"))]
    order_id: String,
    // 从请求体中取数据
    #[extract(source(from = "body", format = "json"))]
    title: String,
    #[extract(source(from = "body", format = "json"))]
    price: f64,
}
#[handler]
async fn edit_order(order_save: OrderSave, res: &mut Response) {
    // 直接把解析好的数据输出到响应中
    res.render(Json(order_save));
}
复制代码
  • Router编写方式:
Router::with_path("/user/<id>").post(edit_order)
复制代码
  • 请求方式:
curl -X "POST" "http://127.0.0.1:7878/user/123456?oid=order_123456" \
     -H 'Content-Type: application/json; charset=utf-8' \
     -d $'{
  "title": "标题",
  "price": 18.88
}'
复制代码
  • 从请求头中取数据
#[derive(Debug, Serialize, Deserialize, Extractible)]
struct OrderSave {
    // 从请求路径中取参数"id"的值
    #[extract(alias = "id", source(from = "param"))]
    user_id: String,
    // 从?后面取参数"oid"的值
    #[extract(alias = "oid", source(from = "query"))]
    order_id: String,
    // 从请求体中取值
    #[extract(alias = "Cookie", source(from = "header"))]
    cookie:String,
    // 从请求体中取数据
    #[extract(source(from = "body", format = "json"))]
    title: String,
    #[extract(source(from = "body", format = "json"))]
    price: f64,
}
#[handler]
async fn edit_order(order_save: OrderSave, req: &mut Request, res: &mut Response) {
    // 需要注意的是,参数中中划线的参数在实体类中暂时解析不出来,需要单独拎出来解析
    let content_type: String = req.header("Content-Type").unwrap();
    println!("{}", content_type);
    res.render(Json(order_save));
}
复制代码
  • Router编写方式:
Router::with_path("/user/<id>").post(edit_order)
复制代码
  • 请求方式:
curl -X "POST" "http://127.0.0.1:7878/user/123456?oid=order_123456" \
     -H 'Content-Type: application/json; charset=utf-8' \
     -H 'Cookie: JSESSIONID=FFF03011504BAD9F042BEBF4435E1CBD; SESSION=NjYxNzlhZjktZjViNi00NDE3LTgzMzAtNWQyZDQ0NGQwNzlm' \
     -d $'{
  "title": "标题",
  "price": 18.88
}'
复制代码
  • 文件上传(带参数)
#[derive(Debug, Serialize, Deserialize, Extractible)]
struct FileName {
    // 同时从请求体中解析出简单类型字段值
    #[extract(source(from = "body"))]
    name: String,
}
// "/upload/<id>"
#[handler]
async fn upload(file_name: FileName, req: &mut Request, res: &mut Response) {
    let id = req.param::<String>("id").unwrap();
    // 从请求体中取出文件
    let file = req.file("file").await;
    if let Some(file) = file {
        // 写入目标路径
        let dest_file = format!("/tmp/{}", &file.name().unwrap());
        if let Ok(x) = std::fs::copy(&file.path(), Path::new(&dest_file)) {
            // 返回响应
            res.render(format!("id:{} \nfile_name:{}  \n文件上传成功:{}", id, file_name.name, &dest_file));
        } else {
            // 写入文件失败
            GlobalError::new(500, "file store failure", "file store failure").write(res);
        }
    } else {
        // 没有取到文件,返回失败
        GlobalError::bad_request("file not found in request", "file not found in request").write(res);
    }
}
复制代码
  • Router编写方式:
Router::with_path("/upload/<id>").post(upload)
复制代码
  • 请求方式:
curl -X "POST" "http://127.0.0.1:7878/upload/123456" \
     -H 'Content-Type: multipart/form-data; charset=utf-8; boundary=__X_PAW_BOUNDARY__' \
     -H 'Cookie: JSESSIONID=FFF03011504BAD9F042BEBF4435E1CBD; SESSION=NjYxNzlhZjktZjViNi00NDE3LTgzMzAtNWQyZDQ0NGQwNzlm' \
     -F "file=" \
     -F "name=hello"
复制代码

结束

到此,基本上大多数使用场景已经囊括进来了,小伙伴们可以根据以上这几个示例编写自己的业务代码。如果还有其他更复杂的应用场景,请参考salvo官方文档


相关文章
|
数据采集 JSON 数据可视化
JSON数据解析实战:从嵌套结构到结构化表格
在信息爆炸的时代,从杂乱数据中提取精准知识图谱是数据侦探的挑战。本文以Google Scholar为例,解析嵌套JSON数据,提取文献信息并转换为结构化表格,通过Graphviz制作技术关系图谱,揭示文献间的隐秘联系。代码涵盖代理IP、请求头设置、JSON解析及可视化,提供完整实战案例。
979 4
JSON数据解析实战:从嵌套结构到结构化表格
|
JSON 监控 网络协议
Bilibili直播信息流:连接方法与数据解析
本文详细介绍了自行实现B站直播WebSocket连接的完整流程。解析了基于WebSocket的应用层协议结构,涵盖认证包构建、心跳机制维护及数据包解析步骤,为开发者定制直播数据监控提供了完整技术方案。
2822 9
|
机器学习/深度学习 JSON 算法
淘宝拍立淘按图搜索API接口系列的应用与数据解析
淘宝拍立淘按图搜索API接口是阿里巴巴旗下淘宝平台提供的一项基于图像识别技术的创新服务。以下是对该接口系列的应用与数据解析的详细分析
|
数据采集 监控 搜索推荐
深度解析淘宝商品详情API接口:解锁电商数据新维度,驱动业务增长
淘宝商品详情API接口,是淘宝开放平台为第三方开发者提供的一套用于获取淘宝、天猫等电商平台商品详细信息的应用程序接口。该接口涵盖了商品的基本信息(如标题、价格、图片)、属性参数、库存状况、销量评价、物流信息等,是电商企业实现商品管理、市场分析、营销策略制定等功能的得力助手。
|
Java API 数据处理
深潜数据海洋:Java文件读写全面解析与实战指南
通过本文的详细解析与实战示例,您可以系统地掌握Java中各种文件读写操作,从基本的读写到高效的NIO操作,再到文件复制、移动和删除。希望这些内容能够帮助您在实际项目中处理文件数据,提高开发效率和代码质量。
1086 4
|
数据采集 前端开发 API
SurfGen爬虫:解析HTML与提取关键数据
SurfGen爬虫:解析HTML与提取关键数据
|
缓存 监控 搜索推荐
【实战解析】smallredbook.item_get_video API:小红书视频数据获取与电商应用指南
本文介绍小红书官方API——`smallredbook.item_get_video`的功能与使用方法。该接口可获取笔记视频详情,包括无水印直链、封面图、时长、文本描述、标签及互动数据等,并支持电商场景分析。调用需提供`key`、`secret`和`num_iid`参数,返回字段涵盖视频链接、标题、标签及用户信息等。同时,文章提供了电商实战技巧,如竞品监控与个性化推荐,并列出合规注意事项及替代方案对比。最后解答了常见问题,如笔记ID获取与视频链接时效性等。
|
存储 缓存 监控
如何高效爬取天猫商品数据?官方API与非官方接口全解析
本文介绍两种天猫商品数据爬取方案:官方API和非官方接口。官方API合法合规,适合企业长期使用,需申请企业资质;非官方接口适合快速验证需求,但需应对反爬机制。详细内容涵盖开发步骤、Python实现示例、反爬策略、数据解析与存储、注意事项及扩展应用场景。推荐工具链包括Playwright、aiohttp、lxml等。如需进一步帮助,请联系作者。
|
JSON API 数据格式
淘宝商品评论API接口系列的应用与数据解析
在电商平台中,用户评论是了解商品质量、服务水平和用户满意度的重要数据来源。淘宝作为中国最大的电商平台,提供了商品评论API接口,帮助开发者获取和分析用户评价数据。本文将介绍淘宝商品评论API接口系列的作用、使用方法,并通过示例展示如何调用API并解析返回的JSON数据。
|
存储 数据采集 JSON
Python爬取某云热歌榜:解析动态加载的歌曲数据
Python爬取某云热歌榜:解析动态加载的歌曲数据

热门文章

最新文章

推荐镜像

更多
  • DNS