【Axum 0.7.9】WindowsでAxum環境構築
Axum をWindows で利用する
この記事では、
Axum の概要
我が国ではこの著書が一つ有名なものと存じます。此書をきっかけにして、
「
余談
私事ですが、getやpostを単なる英単語としか認識していなかったことを鮮明に覚えています。
即ち⋯
そうした理解の上、未だ自信がないのであれば、私からは
本記事で用いるAxum のチュートリアル
なぜ斯うも付属が多いのかと嘆息するを堪え、Usage exampleとあるのを試すことと致します。
開発環境としてのVSCode
ということで、
ここでは既に
rust-analyzer Rust 開発の必需機能
rust-analyzerです。私が感じた利点は次。
-
誤っている箇所が分かる

誤りを指摘されている様子
波線を引いて誤謬を強調される外、マウスカーソルを合わせることで、当該エラーメッセージを確認できるというものです。 -
適当な補完候補が分かる

候補が一覧される
通常にプログラムコードを書く際にも、誤りを訂正せんとする際にも言える事ですが、何の頼りもないのと、有効な候補から選択するのとでは、難易に大きな差があることは明白というもの。殊に、バージョン更新により互換性が失われた場合、候補の一覧からいち早く嫌な予感を察知できます。 -
データ型が分かる

データ型が表示される
は「型推論」を採用しているため、とりあえずRust letと書けばよく、データ型を明記する必要がありません。型推論の明確な欠点として、プログラムコードを見ただけではデータ型が分からないことがあります。そうした欠点を補完して、プログラムの理解に供することができます。
なお、ファイルを開くだけでは機能しません。的外れなフォルダーを開いていても機能しません。rust-analyzerは正しく動作しません。cargo newで生成されるフォルダーを指します。

「フォルダーを開く」から
Postman Web アプリケーションの動作確認
昨日初めて知りました。にわか仕込みの知識で高説上申候。
Postmanでは、

その他にも同類の拡張機能としてREST Clientがありますし、一般のInsomniaというものを推薦していますが、そちらは
Postmanの所感は次。
- ユーザー登録が求められる
拡張機能を利用するだけにしては仰々しいものだと感じましたが、Googleアカウントなどで登録すれば、特に操作もなく完了しました。 -
があるUI
キーボード入力を完全に省略するほどではありませんが、初めて知った私でも充分理解できました。一方で同じく拡張機能であるREST Clientは、.httpファイルを作成し(🤔)、送信内容を手入力(🤔)する手法を取っているらしく、私は全然やりたくありませんでした。私が手入力の有用性に全く思い至らない間は、どのみち無用の長物でしょう。
PowerShell の環境変数
lsが使えるという点です。dirを入力し慣れない方なら、些細なストレス軽減になるでしょう。
さて、
例に、RUST_LOGという環境変数にdebugという値を定めます。この設定の直後、cargo runでプログラムを実行します。
RUST_LOG=debug cargo run
$Env:RUST_LOG = "debug"
cargo run
cargo add
Cargo.tomlというファイルで管理されます。その方法は主に二つ。
- 直接編集する
-
cargo addコマンドに委ねる
直接編集する場合は置いておいて、問題はcargo addの場合にあります。
チュートリアルのCargo.tomlを見てみると、featuresというものが見られます。
[dependencies]
axum = { path = "../../axum" }
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.0", features = ["full"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
単にcargo add serdeなどとした場合、featuresの部分は反映されず、バージョン番号のみが書かれた状態になります。featuresもコマンドで反映するためには、次のように記述することとなります。
cargo add serde --features derive
従って、全ての
cargo add axum
cargo add serde --features derive
cargo add tokio --features full
cargo add tracing
cargo add tracing-subscriber --features env-filter
実演手順
導入・インストールは終えたものとして、実演の手順を示します。
1. cargo new package を作る
axum_example
名前に大文字を含めると文句を言われるので注意。
cargo new axum_example
axum_exampleというフォルダーができるので、
以降は、全てaxum_exampleでの操作となります。cargoコマンドは、Cargo.tomlの存在する位置でなければエラーになります。
treeコマンドで確認すると次のように表示されました。targetフォルダーは中身が多くて邪魔なので、消した上での結果です。
PS C:\⋯\axum_example> rmdir .\target\
Confirm
The item at C:\⋯\axum_example\target\ has children and the Recurse parameter was not specified. If you continue, all children
will be removed with the item. Are you sure you want to continue?
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): y
PS C:\⋯\axum_example> tree /f
Folder PATH listing for volume OS
Volume serial number is ⋯
C:.
│ .gitignore
│ Cargo.lock
│ Cargo.toml
│
└───src
main.rs
2. cargo add crate を追加する
cargo add axum
cargo add serde --features derive
cargo add tokio --features full
cargo add tracing
cargo add tracing-subscriber --features env-filter
3. main.rsを編集する
axum_example/src/main.rsが存在するので、これを編集します。
敢えて環境変数を確認するため、チュートリアルを次の通り改変しております。
use axum::{
http::StatusCode,
response::IntoResponse,
routing::{get, post},
Json,
Router,
serve
};
use serde::{Deserialize, Serialize};
use tokio::net::TcpListener;
use std::env;
// the input to our `create_user` handler
#[derive(Deserialize)]
struct CreateUser {
username: String,
}
// the output to our `create_user` handler
#[derive(Serialize)]
struct User {
id: u64,
username: String,
}
#[tokio::main]
async fn main() {
// initialize logging
let log_level: String = env::var("RUST_LOG").unwrap_or(String::from("info"));
println!("log_level: {log_level}");
env::set_var("RUST_LOG", log_level);
// initialize tracing
tracing_subscriber::fmt::init();
// build our application with a route
let app: Router =
Router::new()
// `GET /` goes to `root`
.route("/", get(root))
// `POST /users` goes to `create_user`
.route("/users", post(create_user));
// run our app with hyper
let listener: TcpListener = TcpListener::bind("127.0.0.1:3000").await.unwrap();
tracing::debug!("listening on {}", listener.local_addr().unwrap());
// serve app
serve(listener, app).await.unwrap();
}
// basic handler that responds with a static string
async fn root() -> &'static str {
"Hello, World"
}
async fn create_user(
// this argument tells axum to parse the request body
// as JSON into a `CreateUser` type
Json(payload): Json<CreateUser>,
) -> impl IntoResponse {
// insert your application logic here
let user: User = User {
id: 1337,
username: payload.username,
};
// this will be converted into a JSON response
// with a status code of `201 Created`
(StatusCode::CREATED, Json(user))
}
4. cargo run プログラムを実行する
環境変数RUST_LOGの値をdebugに定めます。
$Env:RUST_LOG = "debug"
cargo run
または、一行に纏めることもできます。
$Env:RUST_LOG = "debug"; cargo run
localhostの3000番で接続待機するようになります。
5. Postmanで確認する
チュートリアルのプログラムは、GET POST
// build our application with a route
let app: Router =
Router::new()
// `GET /` goes to `root`
.route("/", get(root))
// `POST /users` goes to `create_user`
.route("/users", post(create_user));
Postmanのメニューから、New HTTP Requestを選びます。

New HTTP Requestを選ぶ
GET http://127.0.0.1:3000を記述します。http://localhost:3000でも可。
記述した後、Sendを選んで送信します。

URLを記述してSendを選ぶ
この結果は、rootと実装された内容に基づいていると確認できます。
// basic handler that responds with a static string
async fn root() -> &'static str {
"Hello, World"
}

応答が表示される
ここでは、続けてPOSTに、http://127.0.0.1:3000/usersに変更します。.route("/users", post(create_user))の"/users"という定義によるものです。

POSTを選ぶ

URLを変更する
ここで、JSONデータを送信するため、Headersメニューに記述を加えます。決まりなのでその通りに書くしかありません。
| key | value |
|---|---|
| content-type | application/json |

Headersを編集する
Bodyをraw、JSONに設定し、送信するJSONデータを手入力します。

rowからJSONを選ぶ
送信データの形式はCreateUserとして定められています。
// the input to our `create_user` handler
#[derive(Deserialize)]
struct CreateUser {
username: String,
}
ここでは、{"username": "Axum太郎"}として送信します。

Sendを選ぶ
応答の型式はUserとして定められています。
// the output to our `create_user` handler
#[derive(Serialize)]
struct User {
id: u64,
username: String,
}

応答
1337という数字が入っているのは、まさにcreate_userによる処理の結果です。
async fn create_user(
// this argument tells axum to parse the request body
// as JSON into a `CreateUser` type
Json(payload): Json<CreateUser>,
) -> impl IntoResponse {
// insert your application logic here
let user: User = User {
id: 1337,
username: payload.username,
};
// this will be converted into a JSON response
// with a status code of `201 Created`
(StatusCode::CREATED, Json(user))
}
Discussion