前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【大家的项目】Salvo - 一个简单的 Web 后端框架

【大家的项目】Salvo - 一个简单的 Web 后端框架

作者头像
MikeLoveRust
发布2021-09-08 10:09:14
7270
发布2021-09-08 10:09:14
举报

为什么要写这个框架

因为我笨,无法学会使用 actix-web 等现存的框架。当我想把以前的 go 的 web 服务使用 rust 实现时,一眼看去,似乎每个框架都比 go 里存在框架复杂, 本来 Rust 的学习曲线就够陡峭的了, 又何苦把 Web 框架整得那么复杂?

如何做到足够简单

很多底层的实现 Hyper 都已经实现,所以,一般需求,基于 Hyper 实现应该没有错。Salvo 也是一样。核心功能是提供还用简单的API,以及一个功能强大并且灵活的路由系统。

Salvo 里统一了 Handler 和 Middleware. Middleware 就是 Handler. 通过路由的 before 或者 after 添加到 Router 上。本质上, Middleware 和 Handler 都是处理 Request 请求,并且可能向 Response 写入数据。而 Handler 接收的参数是 Request, Depot, Response 三个, 其中 Depot 用于存储请求处理过程中的临时数据. 为方便书写, 在用不着的情况下可以省略掉某些参数.

代码语言:javascript
复制
use Salvo::prelude::*;

#[fn_handler]
async fn hello_world(_req: &mut Request, _depot: &mut Depot, res: &mut Response) {
    res.render_plain_text("Hello World");
}
#[fn_handler]
async fn hello_world2(res: &mut Response) {
    res.render_plain_text("Hello World");
}

另外路由系统提供的 API 也是极其简单的, 但是, 功能却是强大的. 正常使用需求下, 基本上就是只关注 Router 一个类型即可.

路由系统

我自己感觉路由系统是跟其他的框架不太一样的. Router 可以写平,也可以写成树状。这里区业务逻辑树与访问目录树。业务逻辑树是根据业务逻辑需求,划分 router 结构,形成 router 树,它不一定与访问目录树一致。

正常情况下我们是这样写路由的:

代码语言:javascript
复制
Router::new().path("articles").get(list_articles).post(create_article);
Router::new()
    .path("articles/<id>")
    .get(show_article)
    .patch(edit_article)
    .delete(delete_article);

往往查看文章和文章列表是不需要用户登录的, 但是创建, 编辑, 删除文章等需要用户登录认证权限才可以. Salvo 中支持嵌套的路由系统可以很好地满足这种需求. 我们可以把不需要用户登录的路由写到一起:

代码语言:javascript
复制
Router::new()
    .path("articles")
    .get(list_articles)
    .push(Router::new().path("<id>").get(show_article));

然后把需要用户登录的路由写到一起, 并且使用相应的中间件验证用户是否登录:

代码语言:javascript
复制
Router::new()
    .path("articles")
    .before(auth_check)
    .post(list_articles)
    .push(Router::new().path("<id>").patch(edit_article).delete(delete_article));

虽然这两个路由都有这同样的 path("articles"), 然而它们依然可以被同时添加到同一个父路由, 所以最后的路由长成了这个样子:

代码语言:javascript
复制
Router::new()
    .push(
        Router::new()
            .path("articles")
            .get(list_articles)
            .push(Router::new().path("<id>").get(show_article)),
    )
    .push(
        Router::new()
            .path("articles")
            .before(auth_check)
            .post(list_articles)
            .push(Router::new().path("<id>").patch(edit_article).delete(delete_article)),
    );

<id>匹配了路径中的一个片段, 正常情况下文章的 id 只是一个数字, 这是我们可以使用正则表达式限制 id 的匹配规则, r"<id:/\d+/>".

更多信息可以查看网站 https://salvo.rs

源码地址: https://github.com/salvo-rs/salvo

非常欢迎大家为项目贡献力量,可以通过以下方法为项目作出贡献:

  • 在 issue 中提交功能需求和 bug report;
  • 在 issues 或者 require feedback 下留下自己的意见;
  • 通过 pull requests 提交代码;
  • 在博客或者技术平台发表 Salvo 相关的技术文章。
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-08-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Rust语言学习交流 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么要写这个框架
  • 如何做到足够简单
    • 路由系统
    相关产品与服务
    消息队列 TDMQ
    消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档