Salvo 正在参加 2021 年度 OSC 中国开源项目评选,请投票支持!
Salvo 在 2021 年度 OSC 中国开源项目评选 中已获得 {{ projectVoteCount }} 票,请投票支持!
2021 年度 OSC 中国开源项目评选 正在火热进行中,快来投票支持你喜欢的开源项目!
2021 年度 OSC 中国开源项目评选 >>> 中场回顾
Salvo 获得 2021 年度 OSC 中国开源项目评选「最佳人气项目」 !
授权协议 MIT
开发语言 Rust 查看源码 »
操作系统 跨平台
软件类型 开源软件
所属分类 Web应用开发Web框架
开源组织
地区 国产
投 递 者 Chrislearn
适用人群 未知
收录时间 2021-10-25

软件简介

Salvo 是一个极其简单且功能强大的 Rust Web 后端框架. 仅仅需要基础 Rust 知识即可开发后端服务.

中国用户可以添加我微信(chrislearn), 拉微信讨论群.

功能特色

  • 基于 Hyper, Tokio 开发;
  • 支持 HTTP1, HTTP2 和 HTTP3;
  • 统一的中间件和句柄接口;
  • 路由支持无限层次嵌套;
  • 每一个路由都可以拥有一个或者多个中间件;
  • 集成 Multipart 表单处理;
  • 支持 WebSocket, WebTransport;
  • 支持 OpenAPI;
  • 支持 Acme, 自动从 let's encrypt 获取 TLS 证书.

 快速开始

你可以查看实例代码, 或者访问官网.

Hello World

main.rs 中创建一个简单的函数句柄, 命名为hello, 这个函数只是简单地打印文本 "Hello World".

use salvo::prelude::*;

#[handler]
async fn hello(_req: &mut Request, _depot: &mut Depot, res: &mut Response) {
    res.render(Text::Plain("Hello World"));
}

#[tokio::main]
async fn main() {
    let acceptor = TcpListener::new("127.0.0.1:5800").bind().await;
    let router =  Router::new().get(hello);
    Server::new(acceptor).serve(router).await;
}

中间件

Salvo 中的中间件其实就是 Handler, 没有其他任何特别之处. 所以书写中间件并不需要像其他某些框架需要掌握泛型关联类型等知识. 只要你会写函数就会写中间件, 就是这么简单!!!

use salvo::http::header::{self, HeaderValue};
use salvo::prelude::*;

#[handler]
async fn add_header(res: &mut Response) {
    res.headers_mut()
        .insert(header::SERVER, HeaderValue::from_static("Salvo"));
}
 

然后将它添加到路由中:

Router::new().hoop(add_header).get(hello)
 

这就是一个简单的中间件, 它向 Response 的头部添加了 Header, 查看完整源码.

可链式书写的树状路由系统

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

Router::with_path("articles").get(list_articles).post(create_article);
Router::with_path("articles/<id>")
    .get(show_article)
    .patch(edit_article)
    .delete(delete_article);
 

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

Router::with_path("articles")
    .get(list_articles)
    .push(Router::with_path("<id>").get(show_article));
 

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

Router::with_path("articles")
    .hoop(auth_check)
    .push(Router::with_path("<id>").patch(edit_article).delete(delete_article));
 

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

Router::new()
    .push(
        Router::with_path("articles")
            .get(list_articles)
            .push(Router::with_path("<id>").get(show_article)),
    )
    .push(
        Router::with_path("articles")
            .hoop(auth_check)
            .push(Router::with_path("<id>").patch(edit_article).delete(delete_article)),
    );
 

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

还可以通过 <*> 或者 <**> 匹配所有剩余的路径片段. 为了代码易读性性强些, 也可以添加适合的名字, 让路径语义更清晰, 比如: <**file_path>.

有些用于匹配路径的正则表达式需要经常被使用, 可以将它事先注册, 比如 GUID:

PathFilter::register_wisp_regex(
    "guid",
    Regex::new("[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}").unwrap(),
);
 

这样在需要路径匹配时就变得更简洁:

Router::with_path("<id:guid>").get(index)
 

查看完整源码

文件上传

可以通过 Request 中的 file 异步获取上传的文件:

#[handler]
async fn upload(req: &mut Request, res: &mut Response) {
    let file = req.file("file").await;
    if let Some(file) = file {
        let dest = format!("temp/{}", file.name().unwrap_or_else(|| "file".into()));
        if let Err(e) = std::fs::copy(&file.path, Path::new(&dest)) {
            res.status_code(StatusCode::INTERNAL_SERVER_ERROR);
        } else {
            res.render("Ok");
        }
    } else {
        res.status_code(StatusCode::BAD_REQUEST);
    }
}

提取请求数据

可以轻松地从多个不同数据源获取数据, 并且组装为你想要的类型. 可以先定义一个自定义的类型, 比如:

#[derive(Serialize, Deserialize, Extractible, Debug)]
/// 默认从 body 中获取数据字段值
#[salvo(extract(default_source(from = "body")))]
struct GoodMan<'a> {
    /// 其中, id 号从请求路径参数中获取, 并且自动解析数据为 i64 类型.
    #[salvo(extract(source(from = "param")))]
    id: i64,
    /// 可以使用引用类型, 避免内存复制.
    username: &'a str,
    first_name: String,
    last_name: String,
}
 

然后在 Handler 中可以这样获取数据:

#[handler]
async fn edit(req: &mut Request) {
    let good_man: GoodMan<'_> = req.extract().await.unwrap();
}
 

甚至于可以直接把类型作为参数传入函数, 像这样:

#[handler]
async fn edit<'a>(good_man: GoodMan<'a>) {
    res.render(Json(good_man));
}
 

查看完整源码

OpenAPI 支持

无需对项目做大的改动,即可实现对 OpenAPI 的完美支持。

#[derive(Serialize, Deserialize, ToSchema, Debug)]
struct MyObject<T: ToSchema + std::fmt::Debug> {
    value: T,
}

#[endpoint]
async fn use_string(body: JsonBody<MyObject<String>>) -> String {
    format!("{:?}", body)
}
#[endpoint]
async fn use_i32(body: JsonBody<MyObject<i32>>) -> String {
    format!("{:?}", body)
}
#[endpoint]
async fn use_u64(body: JsonBody<MyObject<u64>>) -> String {
    format!("{:?}", body)
}

#[tokio::main]
async fn main() {
    tracing_subscriber::fmt().init();

    let router = Router::new()
        .push(Router::with_path("i32").post(use_i32))
        .push(Router::with_path("u64").post(use_u64))
        .push(Router::with_path("string").post(use_string));

    let doc = OpenApi::new("test api", "0.0.1").merge_router(&router);

    let router = router
        .push(doc.into_router("/api-doc/openapi.json"))
        .push(SwaggerUi::new("/api-doc/openapi.json").into_router("swagger-ui"));

    let acceptor = TcpListener::new("127.0.0.1:5800").bind().await;
    Server::new(acceptor).serve(router).await;
}

更多示例

您可以从 examples 文件夹下查看更多示例代码, 您可以通过以下命令运行这些示例:

cd examples
cargo run --bin example-basic-auth
 

您可以使用任何你想运行的示例名称替代这里的 basic-auth.

性能

Benchmark 测试结果可以从这里查看:

https://web-frameworks-benchmark.netlify.app/result?l=rust

https://www.techempower.com/benchmarks/#section=data-r21

 

开源协议

Salvo 项目采用 MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)

展开阅读全文

代码

的 Gitee 指数为
超过 的项目

评论

点击加入讨论🔥(31) 发布并加入讨论🔥
发表了资讯
09/13 16:04

Salvo Rust Web 框架 0.72 发布

Salvo 是 Rust 编写的关注人体工程学的 Web 框架,相比其他框架有很多优势: 没有类型体操,使用时基本不需要对 Rust 有深度理解,非常适合新手; 功能全面,支持 HTTP3, Webtransport 等新协议和功能; 官方维护了众多的中间件; 提供了 tower 兼容层,tower 的中间件可以直接拿来使用; 本次更新内容: 允许直接对 Handler 应用中间件,使用更方便; 对元组实现了 Writer 的支持; 提供 SecureMaxSize 中间件,可以在更细的粒...

3
2
发表了资讯
05/30 20:20

赛风 Rust Web 框架 0.68 发布

Salvo 是 Rust 实现的简单好用且功能强大的 Web 后端框架。 不管你是刚刚 Rust 入门还是使用 Rust 做正规项目开发, Salvo 都很适合。近五年时间的持续维护改进,品质有保证。 同时 Rust 可以让你逃离 Axum 等框架无穷无尽的类型体操。更简单的类型系统,更强大的功能。 本次更新: quinn 更新至 0.11 为 OpenAPI 添加 FormFile 和FormFiles 两种可以自动生成文档的类型。 修复 otel-jaeger 不正常的问题。 opentelemetry 相关的...

2
1
发表了资讯
2023/12/14 11:51

Salvo 0.63.0 发布,Rust Web 后端框架

Salvo 是 Rust 实现的简单好用且功能强大的 Web 后端框架。 虽然昨天刚刚发布 0.61, 今天基于 Hyper 1.0 的全新版本就好了。 我们不跟 Axum 比爹爹,我们只跟它比功能,比易用性。 如果你不曾爱上用 Rust 开发 Web 后端,那只是你没有遇到 Salvo. 如果你已经爱上用Axum等其他框架开发后端,那你应该来体会一下 Salvo, 它能带给你的不一样的极致体验。 特色: - 唯一提供完善中文文档的 Rust Web 框架。 - 唯二提供OpenAPI 集成...

2
4
发表了资讯
2023/12/13 11:34

Salvo 0.61.0 发布,Rust Web 后端框架

Salvo 是 Rust 实现的简单好用且功能强大的 Web 后端框架。 这是基于 Hyper 1.0-rc4 的最后一个版本,不久就会发布基于 Hyper 1.0 正式版本的下一个版本。 特色: - 有着比 axum 等更丰富的功能,但却更易于上手。 - 跟 go 等其他语言框架更接近,比 Rust 语言各个 Web 框架更少的类型系统的烦恼。 - 支持 HTTP1, HTTP2 and HTTP3; - 统一的中间件和 Handler 接口,无需任何复杂语言只是,轻松实现中间件。灵活高效。 - 内置表单...

3
1
发表了资讯
2023/11/30 08:53

Salvo 0.59.0 发布,Rust Web 后端框架

Salvo 是 Rust 实现的简单好用且功能强大的 Web 后端框架。 特色: - 有着比 axum 等更丰富的功能,但却更易于上手。 - 跟 go 等其他语言框架更接近,比 Rust 语言各个 Web 框架更少的类型系统的烦恼。 - 支持 HTTP1, HTTP2 and HTTP3; - 统一的中间件和 Handler 接口,无需任何复杂语言只是,轻松实现中间件。灵活高效。 - 内置表单处理,强大的提取器,轻松反序列请求数据到结构体。 - 支持 WebSocket, WebTransport - 对 Op...

3
0
发表了资讯
2023/08/12 17:24

Salvo 0.50.3 发布,Rust Web 后端框架

Salvo 是一个极其简单且功能强大的 Rust Web 后端框架. 仅仅需要基础 Rust 知识即可开发后端服务. 中国用户可以添加我微信(chrislearn), 拉微信讨论群. 基于 Hyper, Tokio 开发; 支持 HTTP1, HTTP2 和 HTTP3; 统一的中间件和句柄接口; 路由支持无限层次嵌套; 每一个路由都可以拥有一个或者多个中间件; 集成 Multipart 表单处理; 支持 WebSocket, WebTransport; 支持 OpenAPI; 支持 Acme, 自动从 let's encrypt 获取 TLS 证书. 本...

2
1
发表了资讯
2023/07/06 16:53

Salvo 0.45 发布, 最强大且最好用的 Rust Web 框架

Salvo 可以说是最强大好用的 Rust Web 框架。 主要功能和更新: 最简单的 Handler 和 Middleware 的写法, 两个概念合二为一; 与众不同的路由系统; 丰富且功能强大的自带的中间件, base auth, jwt auth(支持 oidc), csrf, otel, proxy, flash, cors, session, sse, size limiter, compression.... 自带 Letsencrpyt 支持, 可以轻松获取免费证书, 自带 OpenAPI 支持, 业界最简洁实现, 没有之一; 支持 WebSocket, Http3, WebTranspo...

2
8
发表了资讯
2022/07/05 21:04

Salvo 0.26.1 发布,Request 提取数据大改进

Salvo 是 Rust 语言编写的简单易用, 又不失功能强大的 Web 后端框架. 此版本主要改进了 Request 数据提取的功能: 可以轻松地从多个不同数据源获取数据, 并且组装为你想要的类型. 可以先定义一个自定义的类型, 比如: #[derive(Serialize, Deserialize, Extractible, Debug)] /// 默认从 body 中获取数据字段值 #[extract(default_source(from = "body"))] struct GoodMan<'a> { /// 其中, id 号从请求路径参数中获取,...

0
2
发表了资讯
2022/05/24 08:13

Salvo 0.24.2 发布, 简单强大的 Rust Web 框架

更新内容: 添加了 test 模块, 方便单元测试, 比起之前使用 http::Request::builder 构建 Request 请求简洁很多. 添加解析 Request 请求数据到强类型的功能, 并且支持多数据源组合. 详细介绍 Salvo 是极其简单且功能强大的框架 Handler use salvo::prelude::*; #[fn_handler] async fn hello_world(_req: &mut Request, _depot: &mut Depot, res: &mut Response) { res.render(Text::Plain("Hello World")); } 中间件...

2
7
发表了资讯
2022/05/17 12:42

Salvo 0.23.3 发布, Rust 编写的简单且强大的后端框架

更新内容: 1. 改进中间件执行流程. 2. 改进依赖包结构 github: https://github.com/salvo-rs/salvo Salvo 是一个极其简单且功能强大的 Rust Web 后端框架. 仅仅需要基础 Rust 知识即可开发后端服务. 🎯 功能特色 基于 Hyper, Tokio 开发; 统一的中间件和句柄接口; 路由支持多层次嵌套, 在任何层都可以添加中间件; 集成 Multipart 表单处理; 支持 Websocket; 支持 Acme, 自动从 let's encrypt 获取 TLS 证书; 支持从多个本地...

12
9
发表了资讯
2022/04/19 08:12

Salvo 0.19.0 发布

本次更新内容: - 新增对 Acme 的支持, 可以自动申请 TLS 证书. - 修复路由部分错误 - 重写了 Error.

1
1
发表了资讯
2021/11/22 07:32

Salvo 0.16.5 发布,Rust Web 后端

Salvo 是一个极其简单易用却又功能强大的 Rust Web 后端框架. 仅仅需要基本的 Rust 基础即可写成功能强大的后端服务器, 我们的目标是: 编码最简单, 功能不缺失, 性能有保障. 主要更新功能: 1. BasicAuthValidator 中的 validate 改成了异步. 2. Rustls 和 Native Tls 的支持, 已经证书的热加载. 3. 改进插件系统. 4. 改进 Server 对应的功能. 🎯 功能特色 基于hyper, tokio 的异步 Web 后端框架; 支持 Websocket; 统一的中间...

5
7
没有更多内容
加载失败,请刷新页面
点击加载更多
加载中
下一页
发表了博客
{{o.pubDate | formatDate}}

{{formatAllHtml(o.title)}}

{{parseInt(o.replyCount) | bigNumberTransform}}
{{parseInt(o.viewCount) | bigNumberTransform}}
没有更多内容
暂无内容
发表了问答
{{o.pubDate | formatDate}}

{{formatAllHtml(o.title)}}

{{parseInt(o.replyCount) | bigNumberTransform}}
{{parseInt(o.viewCount) | bigNumberTransform}}
没有更多内容
暂无内容
暂无内容
31 评论
34 收藏
分享
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部