🦀

RustのTokio製WEBフレームワークaxum version 0.5.6 を使ってみた

2022/05/31に公開

概要

axumのversion【0.5.6】を使ってみました!
今回は、フロントから渡されてきた値を取得するために、以下4パターンの値抽出方法を実装しました。

①BodyのJSON値
②Query
③Path
④QueryとPath両方

上記4パターンの実装に関して、①から順番に記述します。

Cargo.tomlは以下のようになります。

Cargo.toml
[package]
name = "example"
version = "0.1.0"
edition = "2021"

[dependencies]
reqwest = "0.11"
axum = "0.5.6"
tokio = { version = "1", features = ["full"] }
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }

コードを参考にする場合はバージョンによる違いにご注意ください。
バージョンが違うと動かない場合があります。

実践①フロントから送るBodyのJSON値を抽出

main.rs
use axum::{
    routing::{post},
    Router,
    response::Json
};
use serde_json::{Value, json};
#[tokio::main]
async fn main() {
    let app = Router::new()
	.route("/api", post(get_body_json_user_id));

    // localhost:3000 で hyper と共に実行する
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
        
}

// body_jsonからuser_idを取得
async fn get_body_json_user_id(body_json: Json<Value>) -> Json<Value> {
    // user_idの取得
    let user_id = match body_json.0.get("user_id") {
        Some(user_id) => user_id,
        None => panic!("error")
    };
    Json(json!({ "user_id": user_id  }))
}

リクエスト内容

実践② Queryから値を抽出

main.rs
use axum::{
    routing::get,
    Router,
    response::Json,
    extract::{Query}
};
use serde::{Serialize, Deserialize};
use serde_json::{Value, json};
use std::collections::HashMap;

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/api", get(get_query_user_id));

    // localhost:3000 で hyper と共に実行する
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
        
}

#[derive(Debug, Deserialize, Serialize)]
struct GetUserIdParams {
    user_id: String,
}

// queryからuser_idを取得
async fn get_query_user_id(Query(params): Query<HashMap<String, String>>) -> Json<Value> {
    let user_id = match  params.get("user_id") {
        Some(user_id) => user_id,
        None => panic!("error")
    };
    Json(json!({ "user_id": user_id  }))
}

リクエスト内容

実践③Pathから値を取得

main.rs
use axum::{
    routing::get,
    Router,
    response::Json,
    extract::{Path}
};
use serde::{Serialize, Deserialize};
use serde_json::{Value, json};

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/api/:user_id", get(get_path_user_id));

    // localhost:3000 で hyper と共に実行する
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
        
}

#[derive(Debug, Deserialize, Serialize)]
struct GetUserIdPath {
    user_id: String,
}

// pathからuser_idを取得
async fn get_path_user_id(Path(path): Path<GetUserIdPath>) -> Json<Value> {
    let user_id = path.user_id;
    Json(json!({ "user_id": user_id  }))
}

リクエスト内容

実践④ QueryとPath両方から値を抽出

main.rs
use axum::{
    routing::get,
    Router,
    response::Json,
    extract::{Path,Query}
};
use serde::{Serialize, Deserialize};
use serde_json::{Value, json};

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/api/users/:user_id/home", get(get_query_and_path_user_id));

    // localhost:3000 で hyper と共に実行する
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
        
}

#[derive(Debug, Deserialize, Serialize)]
struct ExamplePath {
    user_id: String,
}

#[derive(Debug, Deserialize, Serialize)]
struct ExampleQuery {
    search_text: String,
}

// デフォルト値の設定
impl Default for ExampleQuery {
    fn default() -> Self {
        Self { search_text: String::from("") }
    }
}

// QueryとPathから値を抽出
async fn get_query_and_path_user_id(
    Path(path): Path<ExamplePath>,
    example_query: Option<Query<ExampleQuery>>,
) -> Json<Value> {
    let user_id = path.user_id;
    // unwrap_or_default: Okの場合値を返し、Errの場合値の型のデフォルトを返す
    let Query(example_query) = example_query.unwrap_or_default();
    Json(json!({ "user_id": user_id, "search_text": example_query.search_text  }))
}

リクエスト内容

最後に

コードの書き方は、doc.rsを参考にしました。

なお、doc.rsでは、URLの【】部分のバージョンを書き換えることで、自分が見たいバーションのドキュメントを見ることができます。

// 例
https://docs.rs/axum/【0.5.6】/axum/extract/index.html

// 実際のURL
https://docs.rs/axum/0.5.6/axum/extract/index.html

Discussion