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官方文档


相关文章
|
23天前
|
Python
选择和过滤数据DataFrame信息案例解析
该文介绍了如何使用pandas处理DataFrame数据。首先,通过创建字典并调用pd.DataFrame()函数转换为DataFrame。接着展示了使用loc[]选择年龄大于30的记录,iloc[]选取特定位置行,以及query()根据字符串表达式筛选(年龄大于30且城市为北京)数据的方法。
56 1
|
9天前
|
自然语言处理 数据可视化 数据挖掘
带你飞上云端,轻松解析数据——gopup库详细解析--包含安装库教程
本文介绍了Python库gopup,它是一个用于轻松爬取互联网数据的工具,简化了数据收集和处理的过程。文章提供了gopup的安装教程,特别强调了安装时需注意setuptools版本,并给出了PyCharm和命令行两种安装方法。gopup库能获取包括指数、百度和谷歌数据等多种类型的数据。文中还展示了如何使用gopup获取微博指数和豆瓣新片榜数据,并通过代码示例呈现数据和图表。此外,文章提醒了使用时的风险和部分接口的失效情况,并提供了库文档链接以供深入学习。gopup库适用于数据可视化和数据分析,是进行文本挖掘和自然语言处理项目的理想工具。
46 0
带你飞上云端,轻松解析数据——gopup库详细解析--包含安装库教程
|
2天前
|
缓存 负载均衡 网络协议
【亮剑】一次完整的 HTTP 请求过程,包括 DNS 解析、TCP 握手、HTTP 请求和响应等环节
【4月更文挑战第30天】本文介绍了HTTP请求的重要性和详细过程。首先,DNS解析将域名转换为IP地址,通过递归和迭代查询找到目标服务器。接着,TCP三次握手建立连接。然后,客户端发送HTTP请求,服务器处理请求并返回响应。最后,理解这个过程有助于优化网站性能,如使用DNS缓存、HTTP/2、Keep-Alive、CDN和负载均衡等实践建议。
|
4天前
|
前端开发 API UED
AngularJS的$http服务:深入解析与进行HTTP请求的技术实践
【4月更文挑战第28天】AngularJS的$http服务是核心组件,用于发起HTTP请求与服务器通信。$http服务简化了通信过程,通过深入理解和实践,能构建高效、可靠的前端应用。
|
6天前
|
存储 文件存储 数据库
Flutter的持久化存储:使用SharedPreferences等进行数据存储的技术解析
【4月更文挑战第26天】 Flutter应用持久化存储主要使用SharedPreferences,适合存储简单数据类型。通过shared_preferences插件,可轻松进行数据读写。注意异步操作、数据类型限制和安全性,对于复杂需求,可选择SQLite或文件存储。
|
7天前
|
存储 编译器 C语言
C语言基础知识:数据在内存中的存储解析(整数,浮点数)
C语言基础知识:数据在内存中的存储解析(整数,浮点数)
|
8天前
|
Rust 安全 程序员
Rust vs Go:解析两者的独特特性和适用场景
在讨论 Rust 与 Go 两种编程语言哪种更优秀时,我们将探讨它们在性能、简易性、安全性、功能、规模和并发处理等方面的比较。同时,我们看看它们有什么共同点和根本的差异。现在就来看看这个友好而公平的对比。
|
9天前
|
Web App开发 前端开发 Java
SpringBoot之请求的详细解析
SpringBoot之请求的详细解析
22 0
|
9天前
|
存储 缓存 Java
SpringBootWeb请求响应之前言及状态码的详细解析
SpringBootWeb请求响应之前言及状态码的详细解析
11 0
|
13天前
|
数据采集 XML 数据挖掘
使用Python打造爬虫程序之HTML解析大揭秘:轻松提取网页数据
【4月更文挑战第19天】本文介绍了HTML解析在爬虫技术中的重要性,并通过Python的BeautifulSoup库展示了如何解析和提取数据。文章涵盖了HTML文档结构、使用BeautifulSoup的基本方法,如`find_all()`、选择器(标签、类、ID选择器)以及提取文本、属性和链接。此外,还讨论了遍历和处理嵌套元素的技巧。

推荐镜像

更多