Axum

Axum 0.7 と Tokio 1.x のセットアップと非同期ハンドラ完全ガイド

ⓘ本ページはプロモーションが含まれています

Contents

スポンサードリンク

1. プロジェクトの作成と依存クレートの追加

1‑1 プロジェクトの雛形を作る

まずは Cargo の新規プロジェクトを生成します。ターミナルで以下を実行してください。

--bin オプションにより、src/main.rs が自動的に作成されます。

1‑2 依存クレートを Cargo.toml に追加する

推奨の書き方

バージョン番号は「最新安定版が利用可能であること」を示すため、キャレット(^ または 範囲指定(>= を使います。具体的なバージョンは cargo add コマンドで自動取得できます。

手動で書く場合の例(参考)

ポイント
- ^0.7 は「0.7 系列の最新安定版」を意味し、将来 0.8 がリリースされても自動的に上がらない安全策です。
- cargo add は依存追加と同時に Cargo.lock を更新してくれるので、手作業でバージョンを追記するよりミスが減ります。

1‑3 データベースクレート(例: sqlx)を導入する

Axum だけでも動きますが、実務では DB 接続が必要になることが多いです。ここでは PostgreSQL 用プール sqlx::PgPool を例にします。

システム依存パッケージのインストール(Linux/macOS)

  • Ubuntu/Debian 系
    bash
    sudo apt-get update && sudo apt-get install -y libpq-dev build-essential pkg-config
  • Fedora/CentOS 系
    bash
    sudo dnf install postgresql-devel gcc make pkgconfig
  • macOS (Homebrew)
    bash
    brew install postgresql

libpq-dev(PostgreSQL のクライアントヘッダ)は sqlx がコンパイル時に必要です。Windows ユーザーは公式の PostgreSQL インストーラに同梱されている開発ツールをインストールしてください。


2. 最小構成のサーバ実装

2‑1 エントリポイント src/main.rs の全体像

以下のコードは Tokio ランタイム起動 → Axum Router 構築 → HTTP サーバ起動 を最小限にまとめた例です。コメントで各ステップを補足しています。

補足
- #[tokio::main] はデフォルトでマルチスレッドランタイムを生成します。テストやベンチマーク時にシングルスレッドが欲しい場合は #[tokio::main(flavor = "current_thread")] と書き換えてください。
- axum::Server::bind の引数は &SocketAddr で、parse() よりも型安全です。

2‑2 コードのビルドと動作確認


3. 非同期ハンドラとルーティングの実例

3‑1 GET ハンドラ:Path パラメータ取得

概要

URL の一部を変数として受け取り、型安全に処理します。Path<T>serde::Deserialize を実装した型であれば任意の構造体にマッピングできます。

3‑2 POST ハンドラ:JSON ボディの受け取り

概要

クライアントから送られる JSON データを自動でデシリアライズし、Json<T> 型として取得します。エラーが発生した場合は Axum が 400 Bad Request を返すので、ハンドラ側では Result<_, _> を書く必要はありません。

3‑3 Router への登録例

概要

複数エンドポイントをまとめて Router に組み込む方法です。routing::{get, post} をインポートして可読性を高めます。

ポイント
- Router はイミュータブルなビルダーなので、途中で .clone() して別のサブアプリとして再利用できます。


4. 標準 Extractor の活用パターン

4‑1 Path パラメータ抽出(詳細)

Path<T> は URL の変数部分だけを取り出すために使います。以下は構造体で複数パラメータを受け取る例です。

4‑2 Query パラメータ抽出

検索条件やページング情報は Query<T> が便利です。Option<T> を組み合わせると省略可能なパラメータを自然に表現できます。

4‑3 JSON 抽出とバリデーション

serde の属性や外部クレート validator と組み合わせることで、受信した JSON に対するサーバ側の検証ロジックをシンプルに書けます。

備考
validator クレートは cargo add validator@^0.16 --features derive で追加できます。


5. 共有状態とカスタム Extractor の実装

5‑1 State 抽出器で安全にリソースを共有する

概要

データベースプールやキャッシュは Arc<T> に包んで State<Arc<T>> としてハンドラへ注入します。これにより スレッドセーフかつロックフリー なアクセスが可能です。

main での初期化と Router への組み込み

5‑2 カスタム Extractor:認証トークンの検証

概要

FromRequest トレイトを実装すると、リクエスト受信直後に任意の非同期処理(例: JWT の検証や外部 API 呼び出し)を走らせられます。以下は Bearer Token を取得・検証するシンプルな実装です。

ハンドラ側での利用例

注意点
- カスタム Extractor は FromRequest の型引数 B がリクエストボディの型です。ほとんどの場合は axum::body::Body で問題ありませんが、独自のボディタイプを使う場合はトレイト境界を合わせてください。


6. 統一エラーハンドリングとテスト

6‑1 JSON 形式の汎用エラー型

概要

API のクライアントは 同じ構造 のエラーレスポンスを期待します。以下の ApiErrorIntoResponse を実装しているので、任意のハンドラから Result<_, ApiError> を返すだけで JSON 形式に自動変換されます。

ハンドラでの使用例

6‑2 ハンドラ単体テストの書き方

概要

tower::ServiceExt::oneshot を利用すると、実際にサーバを起動せずに Router に対して HTTP リクエストオブジェクトを投げられます。外部依存(DB 等)はモックや MockPool に差し替えてテスト可能です。

DB モックの簡易例(sqlx)

6‑3 ローカル実行手順まとめ

  1. リポジトリのクローン(例)
    bash
    git clone https://github.com/yourname/axum_tokio_demo.git
    cd axum_tokio_demo
  2. 環境変数設定(PostgreSQL を使う場合)
    bash
    export DATABASE_URL=postgres://user:pass@localhost/sample_db
  3. アプリ起動
    bash
    cargo run
    # => 127.0.0.1:3000 がリッスン状態になるはずです
  4. エンドポイントの確認(curl)
    bash
    curl http://127.0.0.1:3000/
    # => "Hello, Axum 0.7 + Tokio!"
  5. テスト実行
    bash
    cargo test --quiet
    # 全てのテストがパスすれば成功です

7. まとめ

  • 依存クレートは緩やかなバージョン指定^0.7, ^1)で管理し、cargo add を活用すると将来のアップデートが楽になります。
  • Tokio ランタイムと Axum Router の組み合わせだけで最小サーバが構築でき、さらに State<Arc<T>> による共有リソースやカスタム Extractor で実務的な要件にも対応可能です。
  • 標準 Extractor(Path, Query, Json)はすべて 非同期に動作し、型安全 なので、バリデーションや認証ロジックを外部クレートと組み合わせてもシンプルに記述できます。
  • エラーハンドリングは 共通の ApiError に集約し、IntoResponse を実装すればハンドラ側はエラー処理を書かずに済みます。
  • tokio::testtower::ServiceExt::oneshot を使えばサーバ起動不要で 高速な単体テスト が可能です。DB など外部依存はモックに差し替えてテストの信頼性を保ちましょう。

以上の手順とコード例をベースにすれば、最新 Axum(0.7 系)上で Tokio の非同期ランタイム を最大限活用した堅牢かつ拡張性の高い Web API が短時間で構築できます。ぜひローカル環境で試し、必要に応じて認証・DB 接続・ミドルウェアを追加して本格的なサービスへと発展させてください。

スポンサードリンク

-Axum