Hiver Tutorial / Hiver教程
This tutorial will guide you through building a complete REST API application with Hiver.
本教程将指导您使用Hiver构建完整的REST API应用程序。
Table of Contents / 目录
- Project Setup / 项目初始化
- Hello World / 你好世界
- Routing / 路由
- Request Handling / 请求处理
- Middleware / 中间件
- Error Handling / 错误处理
- Database Integration / 数据库集成
- Testing / 测试
1. Project Setup / 项目初始化
Create New Project / 创建新项目
# Create new Rust project / 创建新的Rust项目
cargo new my-api --bin
cd my-api
# Add Hiver dependencies / 添加Hiver依赖
cargo add hiver-runtime hiver-http hiver-router hiver-extractors
cargo add hiver-runtime
Update Cargo.toml / 更新Cargo.toml
[dependencies]
hiver-runtime = "0.1"
hiver-http = "0.1"
hiver-router = "0.1"
hiver-extractors = "0.1"
hiver-runtime = "0.1.0-alpha"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
2. Hello World / 你好世界
Minimal Server / 最小服务器
use hiver_http::Server;
use hiver_router::Router;
fn main() -> std::io::Result<()> {
let mut runtime = hiver_runtime::Runtime::new()?;
runtime.block_on(async {
let app = Router::new()
.get("/", || async { "Hello, Hiver!" });
Server::bind("127.0.0.1:8080")
.run(app)
.await?;
Ok(())
})
}
Run the Server / 运行服务器
cargo run
curl http://localhost:8080/
# Hello, Hiver!
3. Routing / 路由
Path Parameters / 路径参数
#![allow(unused)]
fn main() {
use hiver_http::{Request, Response, StatusCode};
use hiver_router::{Router, Params};
use hiver_extractors::Path;
async fn get_user(Path(id): Path<String>) -> Response {
Response::builder()
.status(StatusCode::OK)
.body(format!("User ID: {}", id).into())
.unwrap()
}
let app = Router::new()
.get("/users/:id", get_user);
}
Multiple Methods / 多种方法
#![allow(unused)]
fn main() {
let app = Router::new()
.get("/users", list_users)
.post("/users", create_user)
.get("/users/:id", get_user)
.put("/users/:id", update_user)
.delete("/users/:id", delete_user);
}
Nested Routes / 嵌套路由
#![allow(unused)]
fn main() {
let app = Router::new()
// Note: Router::nest() not yet implemented
// Planned API: .nest("/api/v1", Router::new()
// .get("/users", list_users)
// .post("/users", create_user)
// .get("/posts", list_posts)
// );
.get("/api/v1/users", list_users)
.post("/api/v1/users", create_user)
.get("/api/v1/posts", list_posts);
}
4. Request Handling / 请求处理
JSON Body / JSON请求体
#![allow(unused)]
fn main() {
use serde::Deserialize;
use hiver_extractors::Json;
#[derive(Deserialize)]
struct CreateUserRequest {
name: String,
email: String,
}
async fn create_user(Json(payload): Json<CreateUserRequest>) -> Response {
Response::builder()
.status(StatusCode::CREATED)
.body(format!("Created user: {}", payload.name).into())
.unwrap()
}
}
Query Parameters / 查询参数
#![allow(unused)]
fn main() {
use hiver_extractors::Query;
use std::collections::HashMap;
async fn search_users(Query(params): Query<HashMap<String, String>>) -> Response {
let query = params.get("q").unwrap_or(&String::new());
Response::builder()
.body(format!("Searching for: {}", query).into())
.unwrap()
}
}
Headers / 请求头
#![allow(unused)]
fn main() {
use hiver_extractors::Header;
async fn get_auth_user(Header(authorization): Header<String>) -> Response {
// Validate token / 验证令牌
if authorization.starts_with("Bearer ") {
Response::new("Authorized".into())
} else {
Response::builder()
.status(StatusCode::UNAUTHORIZED)
.body("Unauthorized".into())
.unwrap()
}
}
}
5. Middleware / 中间件
Logging Middleware / 日志中间件
#![allow(unused)]
fn main() {
use hiver_middleware::Middleware;
use hiver_http::Request;
use std::sync::Arc;
struct Logger;
impl Middleware for Logger {
fn handle(
&self,
req: Request,
next: hiver_middleware::Next,
) -> hiver_middleware::BoxFuture<'static, Result<Response, hiver_http::Error>> {
println!("{} {}", req.method(), req.uri());
next.run(req)
}
}
// Applying middleware / 应用中间件
let app = Router::new()
.middleware(std::sync::Arc::new(Logger))
.get("/", handler);
}
CORS Middleware / CORS中间件
#![allow(unused)]
fn main() {
use hiver_middleware::Cors;
let app = Router::new()
.middleware(std::sync::Arc::new(
Cors::new()
.allow_origin("*")
.allow_methods(["GET", "POST", "PUT", "DELETE"])
))
.get("/", handler);
}
6. Error Handling / 错误处理
Custom Error Type / 自定义错误类型
#![allow(unused)]
fn main() {
use thiserror::Error;
#[derive(Error, Debug)]
pub enum AppError {
#[error("User not found")]
UserNotFound,
#[error("Database error: {0}")]
DatabaseError(#[from] sqlx::Error),
#[error("Invalid input: {0}")]
InvalidInput(String),
}
impl AppError {
pub fn status_code(&self) -> StatusCode {
match self {
Self::UserNotFound => StatusCode::NOT_FOUND,
Self::DatabaseError(_) => StatusCode::INTERNAL_SERVER_ERROR,
Self::InvalidInput(_) => StatusCode::BAD_REQUEST,
}
}
}
}
Error Handler / 错误处理器
#![allow(unused)]
fn main() {
async fn handle_error(err: AppError) -> Response {
Response::builder()
.status(err.status_code())
.body(format!(r#"{{"error":"{}"}}"#, err.to_string()).into())
.unwrap()
}
}
7. Database Integration / 数据库集成
Using SQLx / 使用SQLx
cargo add sqlx --features postgres,runtime-tokio
use sqlx::PgPool;
use std::sync::Arc;
// Stateful handlers receive (Request, Arc<S>) / 有状态处理器接收 (Request, Arc<S>)
async fn list_users(
req: Request,
state: Arc<PgPool>,
) -> Result<Json<Vec<User>>, AppError> {
let users = sqlx::query_as::<_, User>("SELECT * FROM users")
.fetch_all(&*state)
.await?;
Ok(Json(users))
}
fn main() -> std::io::Result<()> {
let mut runtime = hiver_runtime::Runtime::new()?;
runtime.block_on(async {
let pool = PgPool::connect("postgres://localhost/mydb").await?;
let app = Router::new()
.get("/users", list_users)
.with_state(pool);
Server::bind("127.0.0.1:8080")
.run(app)
.await?;
Ok(())
})
}
8. Testing / 测试
Unit Test / 单元测试
#![allow(unused)]
fn main() {
#[cfg(test)]
mod tests {
use super::*;
use hiver_http::Request;
#[test]
fn test_hello_world() -> std::io::Result<()> {
let runtime = hiver_runtime::Runtime::new()?;
runtime.block_on(async {
let req = Request::builder()
.uri("/")
.body(())
.unwrap();
let response = hello_world(req).await;
assert_eq!(response.status(), StatusCode::OK);
Ok(())
})
}
}
}
Integration Test / 集成测试
#![allow(unused)]
fn main() {
// tests/api_test.rs
use hiver_http::Server;
use hiver_router::Router;
#[test]
fn test_api_endpoint() -> std::io::Result<()> {
let runtime = hiver_runtime::Runtime::new()?;
runtime.block_on(async {
let app = Router::new()
.get("/api/health", || async { {"status": "ok"} });
let server = Server::bind("127.0.0.1:0")
.run(app)
.await?;
let addr = server.addr();
let url = format!("http://{}/api/health", addr);
let response = reqwest::get(&url).await.unwrap();
assert_eq!(response.status(), 200);
Ok(())
})
}
}
Complete Example / 完整示例
use hiver_http::{Server, Response, StatusCode};
use hiver_router::{Router, Params};
use hiver_extractors::{Json, Path, Query};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Serialize, Deserialize)]
struct User {
id: u32,
name: String,
email: String,
}
#[derive(Debug, Deserialize)]
struct CreateUserRequest {
name: String,
email: String,
}
// In-memory database / 内存数据库
async fn list_users() -> Json<Vec<User>> {
Json(vec![
User { id: 1, name: "Alice".to_string(), email: "alice@example.com".to_string() },
User { id: 2, name: "Bob".to_string(), email: "bob@example.com".to_string() },
])
}
async fn get_user(Path(id): Path<String>) -> Result<Json<User>, StatusCode> {
match id.as_str() {
"1" => Ok(Json(User { id: 1, name: "Alice".to_string(), email: "alice@example.com".to_string() })),
"2" => Ok(Json(User { id: 2, name: "Bob".to_string(), email: "bob@example.com".to_string() })),
_ => Err(StatusCode::NOT_FOUND),
}
}
async fn create_user(Json(payload): Json<CreateUserRequest>) -> Response {
Response::builder()
.status(StatusCode::CREATED)
.body(format!("Created user: {}", payload.name).into())
.unwrap()
}
async fn health() -> &'static str {
"OK"
}
fn main() -> std::io::Result<()> {
let mut runtime = hiver_runtime::Runtime::new()?;
runtime.block_on(async {
let app = Router::new()
.get("/health", health)
.get("/users", list_users)
.post("/users", create_user)
.get("/users/:id", get_user);
println!("Starting server on http://127.0.0.1:8080");
Server::bind("127.0.0.1:8080")
.run(app)
.await?;
Ok(())
})
}
Next Steps / 下一步
- Explore Middleware for advanced request processing
- Learn about Resilience patterns
- Check Observability for monitoring
- See Examples for more
← Previous / 上一页 | Next / 下一页 →