LoginSignup
0
0

More than 3 years have passed since last update.

[翻訳]Rocket Guide - 1 Overview

Last updated at Posted at 2019-11-24

 健忘録としてRustのWebフレームワークであるRocketのガイド、Rocket Guideの内容について翻訳していきます。
 内容は省略する箇所もあるかもしれませんし、翻訳の正確さについては保証しません。
 なお、まえがき部分は省略し、Overviewセクションから始めます。
 内容に間違いなどありましたらコメントにて指摘いただけると幸いです。

Lifecycle

 Rocketの主なタスクは、リクエストを受信し、内容をアプリケーションの処理中に処理したのちに、生成されたレスポンスをクライアントに返すことです。私たちはリクエストからレスポンスまでの一連の流れを"ライフサイクル"と読んでいます。ライフサイクルについて、以下にまとめます。

1.Routing
 受信したHTTPリクエストを、コード上で操作するための構造にパースし、宣言されたルートの記述に一致するリクエストハンドラーを呼び出します。

2.Validation
 受信したリクエストと型や条件が一致するルートが存在するか検査します。バリデーションに失敗した場合、Rocketは次にマッチするルートを検証するか、もしくはエラーハンドラーを返します。

3.Processing
 ルートが関連付けられたリクエストハンドラーは、バリデートされた引数とともに呼び出されます。これは、アプリケーションにおける主要なビジネスロジックを担当します。処理が無事に完了した場合は、レスポンスを生成します。

4.Response
 Processingで生成されたレスポンスが処理されます。適切なHTTPレスポンスを生成し、それをクライアント側に返します。これでライフサイクルは完了です。引き続きリクエストの受信を待機し、受信した場合、再びライフサイクルを処理します。

Routing

 Rocketのアプリケーションは、ルートとハンドラーを中心として回ります。ルートとは、
  ・ 受信したリクエストと紐づけるための、パラメーターの集合。(URLパラメータなど)
  ・ リクエストを処理し、レスポンスを返すためのハンドラー。
の組み合わせのことを指します。
 ハンドラーは、任意の数の引数を受け取り、任意の型を返すシンプルな関数です。

 照合するためのパラメータには、静的パス、動的パス、パスセグメント、フォーム、クエリ文字列、フォーマット指定子、そして本文のデータなどがあります。Rocketではルートを宣言する際に、その他の言語においての関数を修飾するようなやり方(注:Javaにおいてのアノテーションなど)を採用しています。その方が簡単にルートを宣言できるからです。ルートは、照合するためのパラメータの集合とともに宣言されます。ルートの宣言の例は以下の通りです。

#[get("/world")]              // <- ルートの宣言
fn world() -> &'static str {  // <- リクエストハンドラー
    "Hello, world!"
}

 この worldのルート宣言は、静的パス"/world"からのGETリクエストに照合します。worldの例はシンプルですが、より興味深いアプリケーションを作る際には、ルートのパラメータを追加する必要が出てくるでしょう。次回のRequestセクションでは、ルートを設定する際に利用できるオプションについても説明します。

Mounting

 Rocketがリクエストを、ルートを元に受信できるようにするためにはマウントを行う必要があります。

fn main() {
    rocket::ignite().mount("/hello", routes![world]);
}

 マウントの関数は入力として、
  1.ルートの下層に位置する、ベースとなるパス(この例では"/hello")。
  2.派生するルートへの経路を記述するroutes!マクロ(この例ではroutes![world]。複数宣言する場合はroutes![a, b, c]のように記述する)。
 これにより、ignite関数を介してRocketインスタンスが生成され、"/hello"パスにworldのルートがマウントされます。"/hello/world"に対するGETリクエストはworld関数の中で処理されるようになります。
 大抵のケースでは、ベースとなるパスはシンプルに"/"となるでしょう。

NameSpacing

 ルートをモジュールなど、ルートディレクトリ以外の中で宣言する際に、予期せぬエラーに遭遇するかもしれません。

mod other {
    #[get("/world")]
    pub fn world() -> &'static str {
        "Hello, world!"
    }
}

#[get("/hello")]
pub fn hello() -> &'static str {
    "Hello, outside world!"
}

use other::world;

fn main() {
  // error[E0425]: cannot find value `static_rocket_route_info_for_world` in this scope
  rocket::ignite().mount("/hello", routes![hello, world]);
}

これが発生する原因は、routes!マクロはRokectがコードを生成する際に、ルートの名前を構造体の名前として
暗黙的に変換するからです。解決策としては、上記の代わりにこのようにルートの名前を宣言することです。

rocket::ignite().mount("/hello", routes![hello, other::world]);

Launching

 いまやRocketはルートについて把握し、リクエストの待機を開始するためにlaunch関数を呼ぶことができます。この関数は、サーバーを起動し、リクエストの受信まで待機します。リクエストが到達した段階で、Rocketは一致するルートを探し、ルートのハンドラへとリクエストを送ります。
 通常のケースではlaunch関数はmain関数の中で呼ばれるでしょう。先ほどのHello, World!の例の完成形は以下の通りです、

#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use] extern crate rocket;

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

fn main() {
    rocket::ignite().mount("/hello", routes![world]).launch();
}

 #![feature]が記述された行は、Rustの今後リリース予定である機能で、試験的なnightlyチャネルで利用可能です。この行は、crateのルートでは必須となります。(通常はmain.rsに当たります)。同時に、#[macro_use] extern crate rocketを記述することで、rocketのクレートと、すべてのマクロをインポートします。最終的に、main関数で、launchを呼ぶことで、アプリケーションが実行されます。コンソールには以下の表示がされているはずです。

🔧  Configured for development.
    => address: localhost
    => port: 8000
    => log: normal
    => workers: [logical cores * 2]
    => secret key: generated
    => limits: forms = 32KiB
    => keep-alive: 5s
    => tls: disabled
🛰  Mounting '/hello':
    => GET /hello/world (world)
🚀  Rocket has launched from http://localhost:8000

 localhost:8000/hello/worldに接続すると、Hello, world!の表示が確認できるはずです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0