加入社区: 微信(chrislearn) | QQ群: 823441777
- 简单强大 - 零样板代码,会写函数就会写 Handler
- HTTP/1、HTTP/2、HTTP/3 - 开箱即用的全协议支持
- 灵活路由 - 树形路由,中间件可挂载到任意层级
- 自动证书 - 内置 ACME,自动获取和续期 TLS 证书
- OpenAPI - 一流的 OpenAPI 支持,自动生成文档
- WebSocket & WebTransport - 内置实时通信支持
- 基于 Hyper & Tokio - 生产级异步运行时
创建项目:
cargo new hello-salvo
cd hello-salvo
cargo add salvo tokio --features salvo/oapi,tokio/macros编写 src/main.rs:
use salvo::prelude::*;
#[handler]
async fn hello() -> &'static str {
"Hello World"
}
#[tokio::main]
async fn main() {
let router = Router::new().get(hello);
let acceptor = TcpListener::new("127.0.0.1:7878").bind().await;
Server::new(acceptor).serve(router).await;
}运行:
cargo run无需复杂的泛型和 trait,中间件就是普通函数:
#[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)为不同路由分支应用不同的中间件:
Router::new()
// 公开路由
.push(Router::with_path("articles").get(list_articles))
// 需要认证的路由
.push(Router::with_path("articles").hoop(auth_check).post(create_article).delete(delete_article))Handler 可以反序列化请求体,并返回类型化的 JSON 响应:
use salvo::http::ParseError;
use salvo::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
struct CreateTodo {
text: String,
}
#[derive(Serialize)]
struct Todo {
id: u64,
text: String,
}
#[handler]
async fn create_todo(req: &mut Request) -> Result<Json<Todo>, ParseError> {
let payload = req.parse_json::<CreateTodo>().await?;
Ok(Json(Todo {
id: 1,
text: payload.text,
}))
}这种写法需要启用 Serde 的 derive 功能:
cargo add serde --features derive只需将 #[handler] 改为 #[endpoint]:
#[endpoint]
async fn hello() -> &'static str {
"Hello World"
}自动从 Let's Encrypt 获取证书:
let listener = TcpListener::new("0.0.0.0:443")
.acme()
.add_domain("example.com")
.http01_challenge(&mut router)
.quinn("0.0.0.0:443"); // HTTP/3 支持cargo install salvo-cli
salvo new my_project查看完整的社区项目列表:ECOSYSTEM.md。
Salvo 在 Rust Web 框架中性能名列前茅:
如果 Salvo 对你有帮助,欢迎请我喝杯咖啡。
基于 Apache License 2.0 授权。

