Rust + Axum + Shuttle でAPIサーバ構築
RustでAPIサーバを作成し、デプロイしてみたので共有します。
概要
開発環境
- MacbookAir(M1チップ)
Ventura 13.0
- Rust
cargo 1.67.1 (8ecd4f20a 2023-01-10)
- リポジトリのurl:https://github.com/kentakom1213/nu-wiki-mock-pdf-detail
- デプロイ先のurl:https://nu-wiki-mock-pdf-detail.shuttleapp.rs
webサービスのフロントエンドを開発するにあたり、ただデータを返してくれるだけのモックサーバが必要になったため、勉強も兼ねてRustでAPIサーバを建ててみることにしました。
APIの設計
pdfファイルを管理するアプリなので、pdfの一覧と詳細を取得できれば良いです。
/list
:pdfのリストを返します
例
1 | curl https://nu-wiki-mock-pdf-detail.shuttleapp.rs/list |
1 | [ |
/detail/:file_id
:与えられたidを持つpdfファイルの詳細情報を返します
例
1 | curl https://nu-wiki-mock-pdf-detail.shuttleapp.rs/detail/0 |
1 | { |
実装
サーバの設計
リクエストを処理するフローは以下の通り。(下図参照)
- jsonファイルを配置
- データをデータベースに保存
- オブジェクトをjsonとして返す
ここからは、各段階を詳しく説明します。
1.jsonファイルを配置
ファイル構成
ファイル構成はこんな感じにしました。
1 | nu-wiki-mock-pdf-detail |
staticディレクトリのマウント
jsonファイルを/static
においただけでは存在が認識されないため、shuttleのライブラリを使ってマウントします。
1 | use shuttle_static_folder::StaticFolder; |
2.データをデータベースに保存
jsonの読み込み
Rustでjsonの操作を行うライブラリserde
を利用しました。jsonと同じ形式の構造体を作ることで、簡単に json⇄Rustのオブジェクト ができるので便利です。
データベースに追加
データベースと言ってはいますが、SQLなどのリレーショナルデータベースではなく単なるグローバル変数です。 Rustではただグローバルな領域に変数を置いただけではグローバル変数にならないため、Arcという型に包みます。 Arcはスマートポインタであり、 自分が参照された回数をカウントしながら安全な形で同一のデータにアクセスする仕組みです。 また、Arcはデータへの参照を保存するだけで、データの読み込みや書き込みには対応していないため、 RwLockという型で包むことで、複数のスレッドからも安全にデータの読み書きをすることができます。
1 | +------- Arc --------+ |
詳細は以下の記事を参照してください。
3.オブジェクトをjsonとして返す
ルーティング
ルーティングはlib.rs
のaxum
関数内で行います。
axum::Router
オブジェクトに、メソッドチェーンの形でroute
関数を追加していけばいいだけなのでかなり簡単です。
1 | use axum::Router; |
リクエストの処理
上のコードの9行目では/list
へのGETリクエストの時にget_list
関数を呼び出すことを定義しています。
このget_list
関数は下のように定義されています。
引数は上のコードの10行目のwith_state
メソッドで付加されたdb_list
がState
に包まれた状態で渡されます。
全て説明すると大変なので省略しますが、いくつものレイヤーで包まれたデータをメソッドチェーンで剥いて行って、
最終的にJson
オブジェクトとして返すという感じです。
1 | // dbの定義 |
デプロイ
Shuttleという、Rust製のwebアプリを無料でデプロイすることができるサービスを利用しました。 サーバ側の設定などは必要なく、コマンドのみでデプロイできるのは非常に快適でした。
1 | cargo shuttle init # shuttleの初期化 |
今回は試しませんでしたが、データベースへの接続なども無料でできるみたいです👍
詳細は公式のドキュメントやexampleを参照してみてください。
終わりに
今回初めて、Rustでwebアプリをデプロイするところまで挑戦してみました。 よく言われる通り、Rustでのアプリ開発はかなり難しいですが 厳格な型による安心感と保守のしやすさというメリットは圧倒的だなと感じました。
また、shuttleはまだ発展途上だなと思うような場面にも何度か遭遇しましたが、 開発コミュニティのDiscordがかなり活発で、質問を投げるとすぐに返してくれたことも 非常にありがたかったです。
この記事を読んでRustによるweb開発に興味を持ってくださった皆さん、 一緒にRustを勉強してみませんか?