Rust Actix Web
Rust Web 框架的实用对比分析
以下是 Rust Web 框架的实用对比分析,涵盖主要框架(如 Actix-web、Rocket、Warp、Axum 等)的常见使用场景示例,按功能分类整理:
基础路由设置
Actix-web
use actix_web::{get, App, HttpResponse, HttpServer, Responder};
#[get("/")]
async fn hello() -> impl Responder {
HttpResponse::Ok().body("Hello Actix!")
}
说明:定义根路径和动态路径路由,返回字符串响应。
Rocket
#[macro_use] extern crate rocket;
#[get("/")]
fn hello() -> &'static str {
"Hello Rocket!"
}
Warp
use warp::Filter;
let hello = warp::path::end().map(|| "Hello Warp!");
Axum
use axum::{routing::get, Router};
async fn hello() -> &'static str {
"Hello Axum!"
}
JSON 请求/响应处理
Actix-web
use actix_web::{web, App};
#[derive(serde::Serialize, serde::Deserialize)]
struct User {
name: String,
}
async fn add_user(user: web::Json<User>) -> String {
format!("Added user: {}", user.name)
}
Rocket
#[post("/users", data = "<user>")]
fn add_user(user: Json<User>) -> String {
format!("Added user: {}", user.name)
}
Axum
use axum::Json;
async fn add_user(Json(user): Json<User>) -> String {
format!("Added user: {}", user.name)
}
静态文件服务
Actix-web
App::new().service(
actix_files::Files::new("/static", "./static").show_files_listing(),
);
Warp
warp::path("static").and(warp::fs::dir("./static"));
Rocket
#[launch]
fn rocket() -> _ {
rocket::build().mount("/static", FileServer::from("./static"))
}
数据库集成(SQLx 示例)
Actix-web + SQLx
use sqlx::postgres::PgPool;
async fn get_users(pool: web::Data<PgPool>) -> Result<Json<Vec<User>>, Error> {
let users = sqlx::query_as!(User, "SELECT * FROM users")
.fetch_all(pool.get_ref())
.await?;
Ok(Json(users))
}
Axum + SQLx
async fn get_users(Extension(pool): Extension<PgPool>) -> Result<Json<Vec<User>>, Error> {
let users = sqlx::query_as!(User, "SELECT * FROM users")
.fetch_all(&pool)
.await?;
Ok(Json(users))
}
WebSocket 支持
Actix-web
use actix_web_actors::ws;
async fn ws_handler(req: HttpRequest, stream: web::Payload) -> Result<HttpResponse, Error> {
ws::start(MyWebSocket {}, &req, stream)
}
Warp
let ws_route = warp::path("ws")
.and(warp::ws())
.map(|ws: warp::ws::Ws| {
ws.on_upgrade(|websocket| async move {
// WebSocket 逻辑
})
});
中间件(日志记录示例)
Actix-web
App::new()
.wrap(Logger::default())
.service(hello)
Axum
Router::new()
.route("/", get(hello))
.layer(tower_http::trace::TraceLayer::new_for_http());
错误处理
Rocket
#[catch(404)]
fn not_found() -> Json<Value> {
Json(json!({ "error": "Resource not found" }))
}
Warp
let route = warp::path::end()
.and_then(|| async { Err(warp::reject::not_found()) })
.recover(handle_errors);
文件上传
Actix-web
async fn upload(mut payload: web::Payload) -> Result<String, Error> {
let mut bytes = web::BytesMut::new();
while let Some(chunk) = payload.next().await {
bytes.extend_from_slice(&chunk?);
}
// 保存文件逻辑
Ok("File uploaded".into())
}
Rocket
#[post("/upload", data = "<file>")]
async fn upload(file: TempFile<'_>) -> std::io::Result<()> {
file.persist_to("/uploads/file.txt").await
}
测试框架对比
Actix-web 测试示例
#[actix_rt::test]
async fn test_hello() {
let app = test::init_service(App::new().service(hello)).await;
let req = test::TestRequest::get().uri("/").to_request();
let resp = test::call_service(&app, req).await;
assert!(resp.status().is_success());
}
Warp 测试示例
#[tokio::test]
async fn test_hello() {
let api = hello();
let resp = warp::test::request()
.path("/")
.reply(&api)
.await;
assert_eq!(resp.body(), "Hello Warp!");
}
性能对比(概要)
- Actix-web: 基于 Actor 模型,适合高并发场景
- Warp: 基于 Filter 组合,灵活但学习曲线较高
- Axum: 建立在 Tower 生态上,模块化设计
- Rocket: 开发体验友好,但需要 nightly Rust
基于Rust Rocket框架的实例
以下是一些基于Rust Rocket框架的实用示例,涵盖从基础到进阶的应用场景,帮助开发者快速掌握Rocket的核心功能。
JSON请求与响应
use rocket::serde::{json::Json, Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct User {
id: u64,
name: String,
}
#[post("/user", data = "<user>")]
fn create_user(user: Json<User>) -> Json<User> {
user
}
说明:通过serde
实现JSON数据的序列化与反序列化,支持POST请求。
表单处理
use rocket::form::Form;
#[derive(FromForm)]
struct LoginForm {
username: String,
password: String,
}
#[post("/login", data = "<form>")]
fn login(form: Form<LoginForm>) -> String {
format!("Logged in as: {}", form.username)
}
- 说明:解析表单数据并处理用户登录逻辑。
静态文件服务
use rocket::fs::{FileServer, relative};
#[launch]
fn rocket() -> _ {
rocket::build()
.mount("/static", FileServer::from(relative!("static")))
}
- 说明:通过
FileServer
提供静态文件(如HTML/CSS/JS)服务。
数据库集成(Diesel)
use rocket_sync_db_pools::database;
#[database("postgres_db")]
struct DbConn(diesel::PgConnection);
#[get("/users")]
async fn get_users(conn: DbConn) -> Json<Vec<User>> {
conn.run(|c| users::table.load(c)).await.map(Json).unwrap()
}
- 说明:使用
diesel
连接PostgreSQL数据库并查询数据。
身份验证(JWT)
use rocket::http::Status;
use rocket::request::{self, Request, FromRequest};
struct JwtToken(String);
#[rocket::async_trait]
impl<'r> FromRequest<'r> for JwtToken {
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Status> {
// 从Header提取并验证JWT逻辑
Outcome::Success(JwtToken("valid_token".into()))
}
}
#[get("/protected")]
fn protected_route(token: JwtToken) -> String {
format!("Access granted with token: {}", token.0)
}
- 说明:自定义请求守卫实现JWT验证。
WebSocket通信
use rocket::response::stream::{EventStream, Event};
use rocket::tokio::time::{interval, Duration};
#[get("/events")]
fn stream_events() -> EventStream![] {
EventStream! {
let mut interval = interval(Duration::from_secs(1));
while let Some(_) = interval.next().await {
yield Event::data("ping");
}
}
}
- 说明:通过
EventStream
实现服务器推送事件(SSE)。
错误处理
use rocket::response::status::Custom;
use rocket::http::Status;
#[catch(404)]
fn not_found() -> Custom<String> {
Custom(Status::NotFound, "Resource not found".into())
}
- 说明:自定义404错误页面。
配置环境变量
#[launch]
fn rocket() -> _ {
rocket::build()
.configure(rocket::Config::figment().merge(("port", 8000)))
}
- 说明:动态修改服务器端口等配置。
测试路由
#[cfg(test)]
mod tests {
use super::rocket;
use rocket::local::blocking::Client;
use rocket::http::Status;
#[test]
fn test_index() {
let client = Client::tracked(rocket()).unwrap();
let response = client.get("/").dispatch();
assert_eq!(response.status(), Status::Ok);
}
}
- 说明:编写单元测试验证路由逻辑。
更多场景
- 文件上传:使用
TempFile
处理多部分表单上传。 - 速率限制:通过
Fairing
实现API限流。 - 模板渲染:集成
tera
或handlebars
渲染HTML。 - HTTPS支持:配置TLS证书。
- 日志中间件:添加
log
库记录请求日志。
完整示例可参考Rocket官方文档或GitHub仓库的示例目录。
基于Rust Actix-web框架的实例
以下是基于Rust Actix-web框架的实例,涵盖从基础到进阶的功能实现。所有代码均经过简化,确保可直接运行或适配到项目中。
基础HTTP服务
use actix_web::{get, App, HttpResponse, HttpServer, Responder};
#[get("/")]
async fn hello() -> impl Responder {
HttpResponse::Ok().body("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
}
JSON请求与响应
use actix_web::{post, web, App, HttpServer, Responder};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct User {
name: String,
age: u8,
}
#[post("/user")]
async fn create_user(user: web::Json<User>) -> impl Responder {
HttpResponse::Ok().json(user.into_inner())
}
路径参数解析
#[get("/user/{id}")]
async fn get_user(path: web::Path<u32>) -> impl Responder {
HttpResponse::Ok().body(format!("User ID: {}", path))
}
查询参数处理
#[get("/search")]
async fn search(query: web::Query<HashMap<String, String>>) -> impl Responder {
HttpResponse::Ok().json(query.into_inner())
}
静态文件服务
use actix_files::Files;
App::new().service(
Files::new("/static", "./static").show_files_listing(),
)
中间件示例(日志记录)
use actix_web::middleware::Logger;
HttpServer::new(|| {
App::new()
.wrap(Logger::default())
.service(hello)
})
自定义错误处理
use actix_web::error::ErrorNotFound;
async fn custom_404() -> impl Responder {
HttpResponse::NotFound().body("Custom 404 Page")
}
App::new()
.service(web::resource("/").to(hello))
.default_service(web::to(custom_404))
数据库集成(SQLx)
use sqlx::postgres::PgPoolOptions;
#[post("/user")]
async fn add_user(
pool: web::Data<PgPool>,
user: web::Json<User>,
) -> Result<HttpResponse, Error> {
sqlx::query!("INSERT INTO users (name, age) VALUES ($1, $2)", user.name, user.age)
.execute(pool.get_ref())
.await?;
Ok(HttpResponse::Created().finish())
}
WebSocket通信
use actix_web_actors::ws;
#[get("/ws/")]
async fn websocket(req: HttpRequest, stream: web::Payload) -> Result<HttpResponse, Error> {
ws::start(MyWebSocket {}, &req, stream)
}
文件上传
#[post("/upload")]
async fn upload(mut payload: web::Payload) -> Result<HttpResponse, Error> {
let mut bytes = web::BytesMut::new();
while let Some(chunk) = payload.next().await {
bytes.extend_from_slice(&chunk?);
}
std::fs::write("uploaded_file.txt", bytes)?;
Ok(HttpResponse::Ok().finish())
}
JWT认证
use jsonwebtoken::{encode, Header, EncodingKey};
#[post("/login")]
async fn login(credentials: web::Json<Credentials>) -> impl Responder {
let token = encode(
&Header::default(),
&claims,
&EncodingKey::from_secret("secret".as_ref()),
).unwrap();
HttpResponse::Ok().json(json!({ "token": token }))
}
限流中间件
use actix_web_middleware_ratelimit::{RateLimiter, MemoryStore};
App::new()
.wrap(RateLimiter::new(MemoryStore::new(), 100, Duration::from_secs(60)))
测试示例
#[cfg(test)]
mod tests {
use super::*;
use actix_web::test;
#[actix_rt::test]
async fn test_hello() {
let mut app = test::init_service(App::new().service(hello)).await;
let req = test::TestRequest::get().uri("/").to_request();
let resp = test::call_service(&mut app, req).await;
assert!(resp.status().is_success());
}
}
CORS配置
use actix_cors::Cors;
App::new()
.wrap(Cors::default().allow_any_origin())
环境变量配置
use std::env;
let port = env::var("PORT").unwrap_or_else(|_| "8080".to_string());
HttpServer::new(|| App::new()).bind(format!("127.0.0.1:{}", port))?
健康检查端点
#[get("/health")]
async fn health() -> impl Responder {
HttpResponse::Ok().json(json!({ "status": "ok" }))
}
后台任务
use actix_rt::time;
async fn background_task() {
let mut interval = time::interval(Duration::from_secs(60));
loop {
interval.tick().await;
println!("Background task executed");
}
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
actix_rt::spawn(background_task());
HttpServer::new(|| App::new()).bind("127.0.0.1:8080")?.run().await
}
Prometheus监控
use actix_web_prom::PrometheusMetricsBuilder;
let prometheus = PrometheusMetricsBuilder::new("api")
.endpoint("/metrics")
.build()
.unwrap();
App::new()
.wrap(prometheus)
多路由组合
#[get("/api/v1/users")]
async fn list_users() -> impl Responder { /* ... */ }
App::new()
.service(
web::scope("/api/v1")
.service(list_users)
.service(get_user)
)
请求超时设置
use actix_web::middleware::Timeout;
App::new()
.wrap(Timeout::new(Duration::from_secs(5)))
压缩响应
use actix_web::middleware::Compress;
App::new()
.wrap(Compress::default())
结构化日志
use actix_web::middleware::Logger;
use env_logger::Env;
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
App::new()
.wrap(Logger::new("%a %{User-Agent}i %r %s %Dms"))
信号处理(优雅关闭)
use actix_web::rt::System;
let sys = System::new();
let srv = HttpServer::new(|| App::new())
.shutdown_timeout(5)
.bind("127.0.0.1:8080")?;
let _ = srv.run().await;
sys.run().unwrap();
多线程处理
HttpServer::new(|| App::new())
.workers(4) // 设置线程数
.bind("127.0.0.1:8080")?
自定义响应头
#[get("/custom")]
async fn custom_header() -> impl Responder {
HttpResponse::Ok()
.append_header(("X-Custom", "Value"))
.finish()
}
表单处理
#[derive(Deserialize)]
struct FormData {
username: String,
password: String,
}
#[post("/login")]
async fn form_login(form: web::Form<FormData>) -> impl Responder {
HttpResponse::Ok().body(format!("Welcome {}", form.username))
}
完整项目结构和更多高级用法可参考官方文档:https://actix.rs/docs/
基于Rust Warp框架的实例
以下是基于Rust Warp框架的实例,涵盖路由、中间件、错误处理等常见场景,代码格式严格遵循Markdown规范:
基础路由示例
use warp::Filter;
let hello = warp::path!("hello" / String)
.map(|name| format!("Hello, {}!", name));
let root = warp::path::end()
.map(|| "Welcome to Warp");
HTTP方法处理
let post_data = warp::post()
.and(warp::body::json())
.map(|data: serde_json::Value| warp::reply::json(&data));
let delete_item = warp::delete()
.and(warp::path!("items" / u32))
.map(|id| format!("Deleted item {}", id));
路径参数
let user_profile = warp::path!("users" / u32)
.map(|id| format!("User {} profile", id));
let multi_param = warp::path!("blog" / u32 / String)
.map(|id, slug| format!("Blog {}: {}", id, slug));
查询参数
let pagination = warp::path!("list")
.and(warp::query::<HashMap<String, String>>())
.map(|params| format!("Page: {:?}", params));
JSON处理
#[derive(serde::Deserialize)]
struct User {
name: String,
}
let create_user = warp::post()
.and(warp::body::json())
.map(|user: User| format!("Created user: {}", user.name));
文件服务
let static_files = warp::fs::dir("public");
WebSocket
let ws_echo = warp::path("echo")
.and(warp::ws())
.map(|ws: warp::ws::Ws| ws.on_upgrade(|websocket| async {
// 处理WebSocket连接
}));
中间件示例
let with_header = warp::reply::with::header("X-Custom", "Value");
let route = warp::any().map(|| "OK").with(with_header);
日志中间件
let log = warp::log("api");
let route = warp::any().map(|| "OK").with(log);
认证中间件
let auth = warp::header::<String>("authorization")
.and_then(|token| async move {
if token != "secret" {
Err(warp::reject::custom(MyError::Unauthorized))
} else {
Ok(())
}
});
错误处理
let handle_rejection = warp::recover(|err: warp::Rejection| async move {
if err.find::<warp::reject::MethodNotAllowed>().is_some() {
Ok(warp::reply::with_status(
"Method not allowed",
warp::http::StatusCode::METHOD_NOT_ALLOWED,
))
} else {
Ok(warp::reply::with_status(
"Internal error",
warp::http::StatusCode::INTERNAL_SERVER_ERROR,
))
}
});
CORS配置
let cors = warp::cors()
.allow_any_origin()
.allow_methods(vec!["GET", "POST"]);
路由组合
let api_v1 = warp::path("api").and(
warp::path("v1").and(
warp::path("users").and(
warp::get().map(|| "API v1 users")
)
)
);
路径前缀
let admin_routes = warp::path("admin").and(
warp::path("dashboard").map(|| "Admin dashboard")
);
条件路由
let maybe_secure = warp::header::optional::<String>("authorization")
.map(|token| token.is_some());
流式响应
let stream = warp::path("stream")
.map(|| {
let bytes = (0..10).map(|i| format!("{}\n", i));
warp::reply::stream(bytes)
});
压缩响应
let compressed = warp::reply::with::header("content-encoding", "gzip");
let route = warp::any().map(|| "OK").with(compressed);
自定义拒绝
#[derive(Debug)]
struct RateLimited;
impl warp::reject::Reject for RateLimited {}
let limited = warp::any()
.and_then(|| async { Err::<(), _>(warp::reject::custom(RateLimited)) })
.recover(|err: warp::Rejection| async {
if err.find::<RateLimited>().is_some() {
Ok(warp::reply::with_status(
"Rate limited",
warp::http::StatusCode::TOO_MANY_REQUESTS,
))
} else {
Err(err)
}
});
状态码返回
let created = warp::post()
.map(|| warp::reply::with_status("Created", warp::http::StatusCode::CREATED));
内容协商
let accept_json = warp::header::exact("accept", "application/json");
let route = accept_json.and(warp::any()).map(|| warp::reply::json(&true));
表单处理
#[derive(serde::Deserialize)]
struct Login {
username: String,
password: String,
}
let login = warp::post()
.and(warp::body::form())
.map(|login: Login| format!("Logged in as {}", login.username));
多部分表单
let upload = warp::multipart::form()
.and_then(|form: warp::multipart::FormData| async move {
// 处理文件上传
Ok::<_, warp::Rejection>("Upload complete")
});
这些示例覆盖了Warp框架的核心功能,可以直接集成到实际项目中或作为学习参考。每个示例都保持独立性和最小化实现,便于按需组合使用。
基于 Rust Axum 框架的实例
以下是基于 Rust Axum 框架的实例,涵盖从基础路由到高级功能的应用场景。所有示例均以代码片段形式呈现,可直接用于项目开发。
基础路由与请求处理
use axum::{Router, routing::get, response::Html};
async fn hello_world() -> Html<&'static str> {
Ht