83·Web 开发进阶

JSON API 与请求处理

JSON API 与请求处理

学习目标

  1. 掌握完整 CRUD API
  2. 理解 Extractor
  3. 掌握错误处理

核心概念

完整 CRUD

use axum::{
    Router, Json,
    extract::{Path, State},
    http::StatusCode,
    routing::{get, post, put, delete},
};
use serde::{Deserialize, Serialize};
use std::sync::{Arc, Mutex};

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

type Db = Arc<Mutex<Vec<User>>>;

async fn list_users(State(db): State<Db>) -> Json<Vec<User>> {
    let users = db.lock().unwrap();
    Json(users.clone())
}

async fn create_user(
    State(db): State<Db>,
    Json(input): Json<CreateUser>,
) -> (StatusCode, Json<User>) {
    let mut users = db.lock().unwrap();
    let user = User {
        id: users.len() as u32 + 1,
        name: input.name,
        email: input.email,
    };
    users.push(user.clone());
    (StatusCode::CREATED, Json(user))
}

async fn get_user(
    State(db): State<Db>,
    Path(id): Path<u32>,
) -> Result<Json<User>, StatusCode> {
    let users = db.lock().unwrap();
    users.iter()
        .find(|u| u.id == id)
        .cloned()
        .map(Json)
        .ok_or(StatusCode::NOT_FOUND)
}

fn app() -> Router {
    let db: Db = Arc::new(Mutex::new(vec![]));
    Router::new()
        .route("/users", get(list_users).post(create_user))
        .route("/users/{id}", get(get_user))
        .with_state(db)
}

自定义 Extractor

use axum::{extract::FromRequestParts, http::request::Parts};

struct AuthUser {
    user_id: u32,
}

impl<S> FromRequestParts<S> for AuthUser
where
    S: Send + Sync,
{
    type Rejection = StatusCode;

    async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
        let token = parts.headers.get("Authorization")
            .and_then(|v| v.to_str().ok())
            .ok_or(StatusCode::UNAUTHORIZED)?;

        // 验证 token
        Ok(AuthUser { user_id: 1 })
    }
}

async fn protected_route(AuthUser { user_id }: AuthUser) -> String {
    format!("用户 {} 已认证", user_id)
}

小结

Extractor用途
Json<T>JSON 请求体
Path<T>路径参数
Query<T>Query 参数
State<T>共享状态
HeaderMap请求头

练习编辑器

rust
Loading...