salvo 0.9.3

A simple web framework
Documentation

build status build status build status codecov crates.io Download License

🎯 Features

  • Base on latest hyper, tokio;
  • Websocket supported;
  • Serve a static virtual directory from many physical directories;
  • Middlewares support executed before or after handle;
  • Easy routing:
    • Path parameters and regex supported;
    • Tree-like routing system;

⚡️ Quick start

You can view samples here or read docs here.

Create a new rust project:

cargo new hello_salvo --bin

Add this to Cargo.toml

[dependencies]
salvo = "0.9"
tokio = { version = "1", features = ["full"] }

Create a simple function handler in the main.rs file, we call it hello_world, this function just render plain text "Hello World".

use salvo::prelude::*;

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

There are many ways to write function handler.

#[fn_handler]
async fn hello_world(res: &mut Response) {// remove params you don't used.
    res.render_plain_text("Hello World");
}

#[fn_handler]
async fn hello_world(res: &mut Response) -> &'static str {// just return &str
    "Hello World"
}

#[fn_handler]
async fn hello_world(res: &mut Response) -> Result<&'static str, ()> {// return Result
    Ok("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::*;

#[fn_handler]
async fn hello_world(res: &mut Response) {
    res.render_plain_text("Hello World");
}

#[tokio::main]
async fn main() {
    let router = Router::new().get(hello_world);
    let server = Server::new(router);
    server.bind(([0, 0, 0, 0], 7878)).await;
}

Tree-like routing system

use salvo::prelude::*;

#[tokio::main]
async fn main() {
    let router = Router::new()
        .get(index)
        .push(
            Router::new()
                .path("users")
                .before(auth)
                .post(create_user)
                .push(Router::new().path(r"<id:/\d+/>").post(update_user).delete(delete_user)),
        )
        .push(
            Router::new()
                .path("users")
                .get(list_users)
                .push(Router::new().path(r"<id:/\d+/>").get(show_user)),
        );

    Server::new(router).bind(([0, 0, 0, 0], 7878)).await;
}

#[fn_handler]
async fn index(res: &mut Response) {
    res.render_plain_text("Hello world!");
}
#[fn_handler]
async fn auth(res: &mut Response) {
    res.render_plain_text("user has authed\n\n");
}
#[fn_handler]
async fn list_users(res: &mut Response) {
    res.render_plain_text("list users");
}
#[fn_handler]
async fn show_user(res: &mut Response) {
    res.render_plain_text("show user");
}
#[fn_handler]
async fn create_user(res: &mut Response) {
    res.render_plain_text("user created");
}
#[fn_handler]
async fn update_user(res: &mut Response) {
    res.render_plain_text("user updated");
}
#[fn_handler]
async fn delete_user(res: &mut Response) {
    res.render_plain_text("user deleted");
}

More Examples

Your can find more examples in examples folder:

☕ Supporters

Salvo is an open source project. If you want to support Salvo, you can ☕ buy a coffee here.

⚠️ License

Salvo is licensed under either of