Skip to content

Rust Web 服务器

本章节将介绍如何使用 Rust 创建 Web 服务器。

项目设置

创建项目

bash
cargo new --bin web-server
cd web-server

添加依赖

Cargo.toml 文件中添加依赖:

toml
[dependencies]
tokio = { version = "1", features = ["full"] }
axum = "0.6"
serde = { version = "1", features = ["derive"] }
serde_json = "1"

基本服务器

创建简单服务器

rust
use axum::{Router, routing::get, response::Html};

async fn hello() -> Html<&'static str> {
    Html("<h1>Hello, World!</h1>")
}

async fn about() -> Html<&'static str> {
    Html("<h1>About</h1><p>This is a Rust web server.</p>")
}

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/", get(hello))
        .route("/about", get(about));
    
    println!("Server running on http://localhost:3000");
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

运行服务器

bash
cargo run

然后在浏览器中访问 http://localhost:3000

路由和参数

路径参数

rust
use axum::{Router, routing::get, extract::Path};

async fn greet(Path(name): Path<String>) -> String {
    format!("Hello, {}!", name)
}

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/greet/:name", get(greet));
    
    println!("Server running on http://localhost:3000");
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

查询参数

rust
use axum::{Router, routing::get, extract::Query};
use serde::Deserialize;

#[derive(Deserialize)]
struct Params {
    name: String,
    age: Option<u32>,
}

async fn greet(Query(params): Query<Params>) -> String {
    match params.age {
        Some(age) => format!("Hello, {}! You are {} years old.", params.name, age),
        None => format!("Hello, {}!", params.name),
    }
}

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/greet", get(greet));
    
    println!("Server running on http://localhost:3000");
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

请求和响应

JSON 请求

rust
use axum::{Router, routing::post, extract::Json};
use serde::Deserialize;

#[derive(Deserialize)]
struct User {
    name: String,
    email: String,
}

async fn create_user(Json(user): Json<User>) -> String {
    format!("Created user: {} ({})
", user.name, user.email)
}

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/users", post(create_user));
    
    println!("Server running on http://localhost:3000");
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

JSON 响应

rust
use axum::{Router, routing::get, Json};
use serde::Serialize;

#[derive(Serialize)]
struct User {
    id: u32,
    name: String,
    email: String,
}

async fn get_user() -> Json<User> {
    Json(User {
        id: 1,
        name: "John Doe".to_string(),
        email: "john@example.com".to_string(),
    })
}

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/users/1", get(get_user));
    
    println!("Server running on http://localhost:3000");
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

中间件

日志中间件

rust
use axum::{Router, routing::get, middleware::from_fn};

async fn logger_middleware(request: axum::http::Request<axum::body::Body>, next: axum::middleware::Next) -> axum::response::Response {
    let start = std::time::Instant::now();
    let path = request.uri().path().to_string();
    
    let response = next.run(request).await;
    
    let duration = start.elapsed();
    println!("{} took {:?}", path, duration);
    
    response
}

async fn hello() -> &'static str {
    "Hello, World!"
}

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/", get(hello))
        .layer(from_fn(logger_middleware));
    
    println!("Server running on http://localhost:3000");
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

静态文件

提供静态文件

toml
[dependencies]
tower-http = { version = "0.4", features = ["fs"] }
rust
use axum::{Router, routing::get};
use tower_http::services::ServeDir;

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/", get(|| async { "Hello, World!" }))
        .nest_service("/static", ServeDir::new("static"));
    
    println!("Server running on http://localhost:3000");
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

数据库集成

SQLite 集成

toml
[dependencies]
sqlx = { version = "0.6", features = ["sqlite", "runtime-tokio-rustls"] }
rust
use axum::{Router, routing::get, Json};
use serde::Serialize;
use sqlx::SqlitePool;

#[derive(Serialize)]
struct User {
    id: i32,
    name: String,
    email: String,
}

async fn get_users(pool: SqlitePool) -> Json<Vec<User>> {
    let users = sqlx::query_as!(User, "SELECT id, name, email FROM users")
        .fetch_all(&pool)
        .await
        .unwrap();
    
    Json(users)
}

#[tokio::main]
async fn main() {
    let pool = SqlitePool::connect("sqlite:database.db").await.unwrap();
    
    // 创建表
    sqlx::query!("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)")
        .execute(&pool)
        .await
        .unwrap();
    
    // 插入测试数据
    sqlx::query!("INSERT INTO users (name, email) VALUES (?, ?)", "John Doe", "john@example.com")
        .execute(&pool)
        .await
        .unwrap();
    
    let app = Router::new()
        .route("/users", get(get_users))
        .with_state(pool);
    
    println!("Server running on http://localhost:3000");
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

总结

  • 项目设置:使用 cargo new --bin 创建 Web 服务器项目
  • 基本服务器:使用 axum 库创建简单的 Web 服务器
  • 路由和参数:处理路径参数和查询参数
  • 请求和响应:处理 JSON 请求和响应
  • 中间件:添加日志中间件
  • 静态文件:提供静态文件服务
  • 数据库集成:集成 SQLite 数据库

通过本章节的学习,你应该已经掌握了使用 Rust 创建 Web 服务器的方法。