快速開始

安裝 Rust

如果您尚未安裝 Rust,可以使用官方提供的 rustup 安裝 Rust。

Tip

目前 Salvo 支援的最低 Rust 版本為 1.89。請執行 rustup update 確認您已安裝符合要求的 Rust。

編寫第一個 Salvo 程式

建立一個全新的專案:

cargo new hello --bin

將相依項目加入 Cargo.toml

[package]
name = "example-hello"
version.workspace = true
edition.workspace = true
publish.workspace = true
rust-version.workspace = true

[dependencies]
salvo = { workspace = true }
tokio = { workspace = true, features = ["macros"] }
tracing.workspace = true
tracing-subscriber.workspace = true

main.rs 中建立一個簡單的函式處理器,命名為 hello,此函式僅會印出文字 "Hello world"

use salvo::prelude::*;

// Handler for English greeting
#[handler]
async fn hello() -> &'static str {
    "Hello World"
}

// Handler for Chinese greeting
#[handler]
async fn hello_zh() -> Result<&'static str, ()> {
    Ok("你好,世界!")
}

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

    // Bind server to port 8698
    let acceptor = TcpListener::new("0.0.0.0:8698").bind().await;

    // Create router with two endpoints:
    // - / (root path) returns English greeting
    // - /你好 returns Chinese greeting
    let router = Router::new()
        .get(hello)
        .push(Router::with_path("你好").get(hello_zh));

    // Print router structure for debugging
    println!("{router:?}");

    // Start serving requests
    Server::new(acceptor).serve(router).await;
}

恭喜您,您的第一個 Salvo 程式已完成。只需在命令列執行 cargo run,然後在瀏覽器中開啟 http://127.0.0.1:8698 即可。

詳細解讀

此處的 hello_world 是一個 Handler,用於處理使用者請求。#[handler] 可讓函式輕鬆實作 Handler trait,並允許我們以不同方式簡寫函式參數。

  • 原始形式:

    #[handler]
    async fn hello(_req: &mut Request, _depot: &mut Depot, res: &mut Response, _ctrl: &mut FlowCtrl) {
        res.render("Hello world");
    }
  • 您可以省略函式中未使用的參數,例如這裡的 _req_depot_ctrl 皆未使用,可直接省略:

    #[handler]
    async fn hello(res: &mut Response) {
        res.render("Hello world");
    }
  • 任何實作了 Writer trait 的型別皆可作為函式回傳型別。例如 &str 實作了 Writer,當其作為回傳值時,會印出純文字:

    #[handler]
    async fn hello(res: &mut Response) -> &'static str {
        "Hello world"
    }
  • 更常見的情況是,我們需要將 Result<T, E> 作為回傳型別,以便處理函式執行過程中的錯誤。若 TE 皆實作了 Writer,則 Result<T, E> 即可作為回傳值:

    #[handler]
    async fn hello(res: &mut Response) -> Result<&'static str, ()> {
        Ok("Hello world")
    }

靈動的 HTTP3

據說 HTTP3 身輕如燕,令眾多程式設計師心嚮往之,如今 Salvo 助您實現願望,輕鬆享受 HTTP3 帶來的絕佳服務!

首先在 Cargo.toml 中啟用 HTTP3 功能,然後將 main.rs 修改如下:

main.rs
Cargo.toml
use salvo::conn::rustls::{Keycert, RustlsConfig};
use salvo::prelude::*;

// Handler function responding with "Hello World" for HTTP/3 requests
#[handler]
async fn hello() -> &'static str {
    "Hello World"
}

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

    // Load TLS certificate and private key from embedded PEM files
    let cert = include_bytes!("../certs/cert.pem").to_vec();
    let key = include_bytes!("../certs/key.pem").to_vec();

    // Create router with single endpoint
    let router = Router::new().get(hello);

    // Configure TLS settings using Rustls
    let config = RustlsConfig::new(Keycert::new().cert(cert.as_slice()).key(key.as_slice()));

    // Create TCP listener with TLS encryption on port 8698
    let listener = TcpListener::new(("0.0.0.0", 8698)).rustls(config.clone());

    // Create QUIC listener and combine with TCP listener
    let acceptor = QuinnListener::new(config.build_quinn_config().unwrap(), ("0.0.0.0", 8698))
        .join(listener)
        .bind()
        .await;

    // Start server supporting both HTTP/3 (QUIC) and HTTPS (TCP)
    Server::new(acceptor).serve(router).await;
}

Salvo CLI 工具 🛠️

Salvo CLI 是專為 Salvo web 框架設計的工具,能協助您建立整潔、易讀的程式碼,節省時間以投入生活中更有趣的事物。

若您對改進 CLI 有任何想法,或發現需要解決的問題,請隨時提出 issue,我們非常歡迎您的見解。

第 1 步

安裝 CLI 工具:

cargo install salvo-cli

第 2 步

建立新的 Salvo 專案,使用 new 指令後接您的專案名稱:

salvo new project_name

透過這個簡潔的 CLI 工具,您可以快速啟動 Salvo 專案,專注於實現業務邏輯,無需費心專案結構搭建。✨

更多範例

建議直接複製 Salvo 儲存庫,然後執行 examples 目錄下的範例。例如,以下指令可執行 hello 範例:

git clone https://github.com/salvo-rs/salvo
cd salvo/examples
cargo run --bin example-hello

examples 目錄下包含許多範例,皆可透過類似 cargo run --bin example-<name> 的指令執行。