今天,我們來聊聊 Rust 在 Web 開發領域的應用,現在很多的職缺都是backend而工作內容則是在寫API,所以我們來看一下兩個流行的 Web 框架:Actix 和 Rocket。這些框架可以讓 Rust 構建高效能、安全的 api server。
Actix Web 是一個強大、實用且速度極快的 Rust Web 框架。它建立在 actor 系統之上,提供了出色的效能和靈活性。
Cargo.toml
[dependencies]
actix-web = "4"
use actix_web::{get, web, App, HttpServer, Responder};
#[get("/")]
async fn hello() -> impl Responder {
"Hello, Actix Web!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(hello)
})
.bind("127.0.0.1:8080")?
.run()
.await
}
use actix_web::{post, web, App, HttpServer, Responder};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)]
struct Info {
name: String,
age: u32,
}
#[post("/echo")]
async fn echo(info: web::Json<Info>) -> impl Responder {
web::Json(info.0)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(echo)
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Rocket 是另一個受歡迎的 Rust Web 框架,以其簡潔的 API 和強大的功能而聞名。
Cargo.toml
[dependencies.rocket]
version = "0.5.1"
features = ["json"]
#[macro_use] extern crate rocket;
#[get("/")]
fn index() -> &'static str {
"Hello, Rocket!"
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![index])
}
use rocket::serde::Serialize;
use rocket::serde::json::Json;
#[derive(Serialize)]
struct User {
name: String,
age: u8,
}
#[get("/user?<name>&<age>")]
fn user(name: &str, age: u8) -> Json<User> {
Json(User {
name: name.to_string(),
age,
})
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![user])
}
無論使用哪個框架,設計 RESTful API 的原則都是相似的。以下是一個使用 Actix Web 的簡單 CRUD API 示例:
use actix_web::{web, App, HttpServer, Responder, HttpResponse};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)]
struct Task {
id: Option<u32>,
title: String,
completed: bool,
}
// 模擬資料庫操作
async fn create_task(task: web::Json<Task>) -> impl Responder {
// 建立任務邏輯
HttpResponse::Created().json(task.0)
}
async fn get_task(id: web::Path<u32>) -> impl Responder {
// Get任務邏輯
HttpResponse::Ok().json(Task {
id: Some(id.into_inner()),
title: "示例任務".to_string(),
completed: false,
})
}
async fn update_task(id: web::Path<u32>, task: web::Json<Task>) -> impl Responder {
// Update任務邏輯
HttpResponse::Ok().json(task.0)
}
async fn delete_task(id: web::Path<u32>) -> impl Responder {
// delete任務邏輯
HttpResponse::NoContent().finish()
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/tasks", web::post().to(create_task))
.route("/tasks/{id}", web::get().to(get_task))
.route("/tasks/{id}", web::put().to(update_task))
.route("/tasks/{id}", web::delete().to(delete_task))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
在 Web 應用程式中,非同步資料庫操作是關鍵。以下是使用 SQLx 進行非同步 PostgreSQL 操作的示例:
use actix_web::{web, App, HttpServer, Responder};
use sqlx::PgPool;
async fn get_users(db: web::Data<PgPool>) -> impl Responder {
let users = sqlx::query!("SELECT * FROM users")
.fetch_all(db.get_ref())
.await
.unwrap();
web::Json(users)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let pool = PgPool::connect("postgres://username:password@localhost/database")
.await
.expect("無法連接到資料庫");
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(pool.clone()))
.route("/users", web::get().to(get_users))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Web 框架通常提供中間件功能來處理橫切關注點,如日誌記錄、認證等。以下是 Actix Web 中使用中間件的範例:
use actix_web::{web, App, HttpServer, Responder, HttpResponse};
use actix_web::middleware::Logger;
async fn index() -> impl Responder {
HttpResponse::Ok().body("Hello, World!")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init();
HttpServer::new(|| {
App::new()
.wrap(Logger::default())
.route("/", web::get().to(index))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Rust 的 Web 開發生態系統正在快速成長,提供了高效能、類型安全和優秀的開發體驗。無論是選擇 Actix Web 還是 Rocket,都能夠構建出安全、高效的 Web 應用程式,缺點的話應該就是開發的時間會比其他語言框架還要長,而且相關的工程師難找。