Quick Start
Installing Rust
If you don’t have Rust yet, we recommend you use rustup
to manage your Rust installation. The official rust guide has a wonderful section on getting started.
Salvo currently has a minimum supported Rust version 1.75. Running rustup update
will ensure you have the latest and greatest Rust version available. As such, this guide assumes you are running Rust 1.75 or later.
Write first app
Create a new rust project:
cargo new hello_salvo --bin
Add this to Cargo.toml
[package]
name = "hello"
version = "0.1.0"
edition = "2021"
publish = false
[dependencies]
salvo = "0.64.0"
tokio = { version = "1", features = ["macros"] }
tracing = "0.1"
tracing-subscriber = "0.3"
Create a simple function handler in the main.rs file, we call it hello
, this function just render plain text "Hello world"
. In the main
function, we need to create a root Router first, and then create a server and call it's bind
function:
use salvo::prelude::*;
#[handler]
async fn hello() -> &'static str {
"Hello World"
}
#[tokio::main]
async fn main() {
tracing_subscriber::fmt().init();
let router = Router::new().get(hello);
let acceptor = TcpListener::new("127.0.0.1:5800").bind().await;
Server::new(acceptor).serve(router).await;
}
Congratulations! Your first app has done! Just run cargo run
to run this app.
More about handler
There are many ways to write function handler.
The orginal format is:
#[handler] async fn hello(_req: &mut Request, _depot: &mut Depot, res: &mut Response, _ctrl: &mut FlowCtrl) { res.render("Hello world"); }
You can omit function arguments if they are not used, like
_req
,_depot
,_ctrl
in this example:#[handler] async fn hello(res: &mut Response) { res.render("Hello world"); }
Any type can be function handler's return value if it implements
Writer
. For example&str
implementsWriter
and it will render string as plain text:#[handler] async fn hello(res: &mut Response) -> &'static str {// just return &str "Hello world" }
The more common situation is we want to return a
Result<T, E>
to implify error handling. IfT
andE
implementsWriter
,Result<T, E>
can be function handler's return type:#[handler] async fn hello(res: &mut Response) -> Result<&'static str, ()> {// return Result Ok("Hello world") }
Use HTTP3
First you need to enable feature http3
in Cargo.toml
, and then change main.rs
like this:
use salvo::conn::rustls::{Keycert, RustlsConfig};
use salvo::prelude::*;
#[handler]
async fn hello() -> &'static str {
"Hello World"
}
#[tokio::main]
async fn main() {
tracing_subscriber::fmt().init();
let cert = include_bytes!("../certs/cert.pem").to_vec();
let key = include_bytes!("../certs/key.pem").to_vec();
let router = Router::new().get(hello);
let config = RustlsConfig::new(Keycert::new().cert(cert.as_slice()).key(key.as_slice()));
let listener = TcpListener::new(("127.0.0.1", 5800)).rustls(config.clone());
let acceptor = QuinnListener::new(config, ("127.0.0.1", 5800))
.join(listener)
.bind()
.await;
Server::new(acceptor).serve(router).await;
}
[package]
name = "example-hello-h3"
version = "0.1.0"
edition = "2021"
publish = false
[dependencies]
salvo = { workspace = true, features = ["quinn"] }
tokio = { version = "1", features = ["macros"] }
tracing = "0.1"
tracing-subscriber = "0.3"
Run more examples
The absolute fastest way to start experimenting with Salvo is to clone the Salvo repository and run the included examples in the examples/
directory. For instance, the following set of commands runs the hello
example:
git clone https://github.com/salvo-rs/salvo.git
cd salvo
cargo run --bin example-hello
There are numerous examples in the examples/
directory. They can all be run with cargo run --bin example-<name>
.