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との連携)やエラーハンドリングの実装に挑戦してみましょう!