あっぽログ
← 記事一覧に戻る

RustでRocketを使ったWebアプリ入門:セットアップからJSONレスポンスまで

Rocketとは?

Rocketは、Rustで書かれたWebフレームワークのひとつです。マクロを活用した直感的なAPIが特徴で、ルーティングの定義やリクエスト/レスポンスの処理を少ないコード量で記述できます。

同じRust製フレームワークのAxumやActix-webと比べると、「使い心地のよさ」を優先した設計になっており、Rust初心者にも比較的とっつきやすいフレームワークです。

この記事では、Rocketを使ってWebアプリを一から作りながら基本的な使い方を学んでいきます。


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

まず、Cargoで新しいプロジェクトを作成します。

cargo new rocket-app
cd rocket-app

次に Cargo.toml に依存関係を追加します。

[dependencies]
rocket = { version = "0.5", features = ["json"] }
serde = { version = "1", features = ["derive"] }

features = ["json"] を指定することで、JSONの送受信に必要な機能が有効になります。


最初のハンドラを書く

src/main.rs を以下のように書き換えましょう。

#[macro_use]
extern crate rocket;

#[get("/")]
fn index() -> &'static str {
    "Hello, Rocket!"
}

#[launch]
fn rocket() -> _ {
    rocket::build().mount("/", routes![index])
}

コードの解説

マクロ / 関数役割
#[get("/")]GETメソッドのルートを定義する
#[launch]アプリのエントリポイントを示す
rocket::build()Rocketインスタンスを生成する
.mount("/", routes![...])ベースパスにハンドラを登録する

起動してみましょう。

cargo run

http://localhost:8000/ にアクセスすると Hello, Rocket! が表示されます。


パスパラメータを受け取る

URLの一部を動的に受け取るには、以下のように書きます。

#[get("/hello/<name>")]
fn hello(name: &str) -> String {
    format!("こんにちは、{}さん!", name)
}

<name> の部分がパスパラメータです。関数の引数名と一致させる必要があります。

mount にも追加します。

#[launch]
fn rocket() -> _ {
    rocket::build().mount("/", routes![index, hello])
}

http://localhost:8000/hello/Taro にアクセスすると「こんにちは、Taroさん!」と表示されます。


クエリパラメータを受け取る

?key=value 形式のクエリパラメータは次のように取得します。

#[get("/search?<keyword>")]
fn search(keyword: &str) -> String {
    format!("「{}」を検索中...", keyword)
}

http://localhost:8000/search?keyword=Rust にアクセスすると「「Rust」を検索中...」と表示されます。

クエリパラメータを省略可能にしたい場合は Option<&str> を使います。

#[get("/search?<keyword>")]
fn search(keyword: Option<&str>) -> String {
    match keyword {
        Some(kw) => format!("「{}」を検索中...", kw),
        None => "キーワードを入力してください".to_string(),
    }
}

JSONレスポンスを返す

実際のAPIでは、JSONを返すことが多いですね。Rocketでは serde と組み合わせて簡単にJSONレスポンスを返せます。

use rocket::serde::json::Json;
use rocket::serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
struct User {
    id: u32,
    name: String,
    email: String,
}

#[get("/users/<id>")]
fn get_user(id: u32) -> Json<User> {
    let user = User {
        id,
        name: format!("User{}", id),
        email: format!("user{}@example.com", id),
    };
    Json(user)
}

Json<T> 型でラップするだけで、自動的に Content-Type: application/json のレスポンスになります。

http://localhost:8000/users/1 にアクセスすると、以下のようなJSONが返ります。

{
  "id": 1,
  "name": "User1",
  "email": "user1@example.com"
}

POSTリクエストでJSONを受け取る

クライアントからJSONを受け取る場合は以下のように書きます。

use rocket::serde::json::Json;

#[derive(Deserialize)]
#[serde(crate = "rocket::serde")]
struct NewUser {
    name: String,
    email: String,
}

#[post("/users", data = "<new_user>")]
fn create_user(new_user: Json<NewUser>) -> String {
    format!("{}({})を登録しました!", new_user.name, new_user.email)
}

data = "<new_user>" でリクエストボディを受け取ることを示し、Json<NewUser> で自動的にデシリアライズされます。


まとめ

この記事では、Rocketの基本的な使い方を学びました。

  • #[get] / #[post] マクロでルートを定義できる
  • パスパラメータ<name> の形式で受け取れる
  • クエリパラメータは関数引数に同名の変数を定義するだけ
  • JSONレスポンスJson<T> でラップするだけで返せる
  • JSONリクエストdata = "<変数>"Json<T> で受け取れる

Rocketはマクロの力でルーティングをシンプルに記述でき、RustのWebフレームワーク入門として非常におすすめです。次のステップとしては、データベース(Diesel / SQLxとの連携)やエラーハンドリングの実装に挑戦してみましょう!

← 記事一覧に戻る