RustでのWebアプリケーションの実装例

はじめに

この記事では、RustでのWebアプリケーションの実装例を紹介したいと思います。

下記が、実際に作成したものです。 内容としては、よくあるサッカー関連のまとめサイトです。 Footballまとめ

背景

最近使っているアプリの使い勝手が悪くなってきたのもあり、自分で実装してみようと思い立ちました。
作るもの自体はシンプルであることはわかっていたので、言語選択としては自分が使ったことがなく、興味があるものをということで、Rustを選びました。

ソースコード

ソースコードは下記で公開しています。 GitHub - kazu9su/football-matome

使用したライブラリなど

Webフレームワーク

  • nickel

GitHub - nickel-org/nickel.rs: An expressjs inspired web framework for Rust

Expressにインスパイアされたシンプルなフレームワーク
単純なルーティングの定義などができます。
RustのWebフレームワークの選択肢はあまりなく、現状ではこのnickelかironの二択という感じでした。
Readmeに書いてあるExampleがnickelのほうがシンプルだったのでnickelを選択しました。

ORM

GitHub - diesel-rs/diesel: A safe, extensible ORM and Query Builder for Rust

せっかくなのでORMも使ってみようかなーということで導入しました。

HTTPクライアント

  • hyper

github.com

外部サイトにリクエストもしているので利用しました。

Mocking

  • mockito

github.com

外部リクエストしているところのテストで使うために導入。内部的には実際にHTTPリクエストしているようです。

ディレクトリ構成

下記のような構成にしました。 Rustのお作法的な構成はわからなかったので、一般的なWebフレームワークのディレクトリ構成を参考にしました。

src/
│├ bin/
│├ config/
│├ controllers/
│├ libraries/
│├ models/
│└ services/
└ tests/

どの層にどのコードを含めるかということについては、model層, service層が一番迷いました。
今回は、model層はDBとのやりとり、service層はそれに関わらずビジネスロジックの実装を持つという決めでやってみました。 しかし、型をどこで定義するかなどは最後まで悩みました。
具体的にはservice層でレスポンスに使う型を定義 *1 しましたが、
ここで定義するのが適切なのか、などは実際に複数人でプロダクトを作るときは問題になりそうだなーと思いました。 librariesには、Webの文脈に関係なく使用できるものを含めました。 testsには、いわゆるintegration testが含まれており、内部実装は各ファイル内でテストします。(下記参照)

テスト

Rustではテストは標準機能として提供されています。

テストの書き方

関数に対して #[cfg(test)] とコメントを作ることでテストを定義できるので、同一ファイル内にテストを書いていくことができます。

https://github.com/kazu9su/football-matome/blob/master/src/services/feed_service.rs#L46

実装が複雑になればテストコードと合わせて行数が倍で増えていくことが予想できますが、そうなったらそもそもファイルを分けるべきであるという考え方もあるので、一長一短かなと思いました。

DBを使用したテストをするなら

また、特にWebアプリケーションを作るという文脈で気をつけなければいけないことは、Rustのテストはデフォルトでマルチスレッドで実行されるということです。
これは、DBを使ったテストでは実行毎に結果が違うというデメリットになってしまうので、明示的にシングルスレッドで実行することを宣言しましょう。

cargo test -- --test-threads=1

また、テストコード中でデバッグしたいときには、 nocaptureオプションをつけると println!() の結果などを表示できるようになるので便利です。

cargo test -- --test-threads=1 --nocapture

Mockitoを使ったテスト

Mockitoは特定のURLでMockサーバーを起動するので、実装時点で、URLを引数として受け取るようにしておけば、スムーズにテストできます。

https://github.com/kazu9su/football-matome/blob/09464e44a0d257cb493cd6473557ff112e6905a3/src/libraries/rss_retriever/retriever.rs#L119

まとめ

今回はRustでのWebアプリケーションの実装例として自分で作ったアプリケーションを紹介しました。
Webを漁ってもなかなか出てこなかったりしたので、RustでWebアプリケーションを作ってみたいと思っている方の参考になれば幸いです。