0Pricing
Learn Rust Coding · レッスン

プロジェクトのセットアップ

APIを構成します

「プロジェクトのセットアップ」はCoddyKit上の無料Learn Rust Codingレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLearn Rust Coding学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Learn Rust Codingコースには全4レッスンが含まれています。

RustでREST APIを構築する

このコースでは、Rustで小規模なREST APIを構築します。Tokio(非同期ランタイム)とTower(ミドルウェア)を基盤とするAxum Webフレームワークを使用します。Axumは使いやすく、型安全で、本番環境でも広く使われています。

この最初のレッスンではプロジェクト構成を設定し、後のレッスンでルート、モデル、データベース、テストを追加できるようにします。

プロジェクトを作成する

Cargoから始めます。バイナリプロジェクトを作成すると、エントリポイントとしてsrc/main.rsが用意されます。

  • cargo new rest_apiでフォルダーを作成します。
  • cd rest_apiでそのフォルダーに移動します。
  • cargo runでビルドして実行します。

これらはシェルおよびcargoのコマンドであり、実行可能なRustコードの断片ではありません。

// terminal
// cargo new rest_api
// cd rest_api
// cargo run

依存関係を追加する

Axum APIでは、Cargo.tomlにいくつかのクレートが必要です。

  • ルーティングとハンドラーにはaxum。
  • 非同期ランタイムにはtokio。
  • JSONのシリアライズにはserde。
// Cargo.toml
// [dependencies]
// axum = "0.7"
// tokio = { version = "1", features = ["full"] }
// serde = { version = "1", features = ["derive"] }
// serde_json = "1"

非同期ランタイム

Webサーバーは多数の接続を同時に処理するため、Axumは非同期です。#[tokio::main]属性はTokioランタイムを起動し、非同期のmainを実際のエントリポイントに変換します。各ハンドラーでは.awaitを使ってノンブロッキングI/Oを実行できます。

// src/main.rs
use tokio;

#[tokio::main]
async fn main() {
    println!("runtime started");
}

最小構成のサーバー

最小構成のAxumアプリケーションでは、Routerを構築し、TCPリスナーをバインドして、サービスを開始します。単一のルートでGET /を文字列を返すハンドラーに割り当てます。ハンドラーは、IntoResponseを実装する値を返す非同期関数にすぎません。

use axum::{routing::get, Router};

#[tokio::main]
async fn main() {
    let app = Router::new().route("/", get(root));
    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
        .await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

async fn root() -> &'static str {
    "Hello, API!"
}

ルーティングの仕組み

Routerは、パスとHTTPメソッドをハンドラーに対応付けます。.route(path, method(handler))の呼び出しをつなげてエンドポイントを登録します。get、post、put、deleteなどのメソッドヘルパーはaxum::routingから提供されます。同じパスに複数のメソッドを組み合わせることもできます。

use axum::{routing::{get, post}, Router};

async fn list() -> &'static str { "list" }
async fn create() -> &'static str { "created" }

fn build_router() -> Router {
    Router::new()
        .route("/items", get(list).post(create))
        .route("/health", get(|| async { "ok" }))
}

推奨されるモジュール構成

APIが大きくなったら、1つの巨大なmain.rsにまとめるのではなく、コードをモジュールに分割します。

  • main.rs — 起動処理とサーバーの接続設定。
  • routes.rs — ルーターの定義。
  • handlers.rs — リクエストハンドラー。
  • models.rs — データ構造。

この分離により、各ファイルの役割が明確になり、テストしやすくなります。

// src/main.rs
mod routes;
mod handlers;
mod models;

#[tokio::main]
async fn main() {
    let app = routes::build();
    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
        .await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

共有アプリケーション状態

多くのAPIでは、データベースプールやインメモリストアなどの共有状態が必要です。Axumでは、ルーターに.with_state(state)を指定して状態を保持します。ハンドラーはStateエクストラクターを使って状態を受け取ります。状態はCloneである必要があるため、変更可能なデータはArcとロックでラップします。

use axum::{routing::get, Router, extract::State};
use std::sync::{Arc, Mutex};

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

async fn count(State(db): State<Db>) -> String {
    let n = db.lock().unwrap().len();
    format!("{} items", n)
}

fn build(db: Db) -> Router {
    Router::new().route("/count", get(count)).with_state(db)
}

JSONを返す

JSONを送信するには、シリアライズ可能な値をaxum::Jsonでラップします。serdeを使って構造体にSerializeを導出すると、Axumが適切なコンテンツタイプとボディを自動的に設定します。

use axum::Json;
use serde::Serialize;

#[derive(Serialize)]
struct Status {
    service: String,
    healthy: bool,
}

async fn health() -> Json<Status> {
    Json(Status { service: "api".into(), healthy: true })
}

設定とポート

デモではポートをハードコードしても問題ありませんが、実際のサービスでは環境から設定を読み取ります。std::env::varをデフォルト値とともに使用します。これにより、再コンパイルせずにバインドアドレスを変更でき、コンテナ環境とも連携しやすくなります。

use std::env;

async fn main_inner() {
    let port = env::var("PORT").unwrap_or_else(|_| "3000".to_string());
    let addr = format!("0.0.0.0:{}", port);
    println!("binding to {}", addr);
    // bind and serve with addr ...
}

セットアップをまとめる

完全な起動処理では、ルートと共有状態を含むルーターを構築し、ポートを読み取り、リスナーをバインドして、サービスを開始します。この骨組みができたら、次のレッスンで実際のエンドポイント、モデル、永続化機能を追加します。

use axum::{routing::get, Router};
use std::sync::{Arc, Mutex};

#[tokio::main]
async fn main() {
    let db = Arc::new(Mutex::new(Vec::<String>::new()));
    let app = Router::new()
        .route("/health", get(|| async { "ok" }))
        .with_state(db);
    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
        .await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

理解度チェック

プロジェクトのセットアップについての理解度を確認しましょう。

まとめ

RustのREST APIプロジェクトをセットアップしました。

  • cargo newを使い、axum、tokio、serdeを追加します。
  • #[tokio::main]が非同期ランタイムを提供します。
  • Routerがパスとメソッドを非同期ハンドラーに対応付けます。
  • .with_stateとStateエクストラクターを使ってデータを共有します。
  • コードをルート、ハンドラー、モデルのモジュールに分割し、ポートを環境から読み取ります。

よくある質問

「プロジェクトのセットアップ」レッスンは無料ですか?

はい。「プロジェクトのセットアップ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Learn Rust Codingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Learn Rust Codingコースには全4レッスンが含まれています。

「プロジェクトのセットアップ」で何を学びますか?

APIを構成します ブラウザで直接実行するハンズオンコードでLearn Rust Codingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Learn Rust Codingを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのLearn Rust Codingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「プロジェクトのセットアップ」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このLearn Rust Codingレッスンでコードを書いて実行できますか?

はい。すべてのLearn Rust Codingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. プロジェクトのセットアップ
  2. エンドポイントとモデル
  3. データベース統合
  4. APIのテスト
← Learn Rust Codingに戻る