前回の記事では、非常にシンプルなHelloWorldを表示するだけのサーバーを作成しIronの基礎を紹介しました。
今回はRouterと呼ばれるMiddlewareを利用して複数のURLに対応したサーバーを作成しました。
routerをCargo.tomlに追加
routerを利用するためにCargo.toml
に以下のようrouterをに追加します
[dependencies] ...other dependencies... router = "*"
Router
コードの完成形は以下の様です:
extern crate iron; extern crate router; use iron::prelude::*; use iron::status; use iron::modifiers::{Redirect}; use router::{Router, url_for}; fn main() { fn top_handler(_: &mut Request) -> IronResult<Response> { Ok(Response::with((status::Ok, "Welcome!"))) } fn redirect_handler(req: &mut Request) -> IronResult<Response> { let ref top_url = url_for(req, "index", ::std::collections::HashMap::new()); return Ok(Response::with((status::Found, Redirect(top_url.clone())))) } fn greet_handler(req: &mut Request) -> IronResult<Response> { let ref router = req.extensions.get::<Router>(); let ref name = router .unwrap() .find("name") .unwrap(); return Ok(Response::with( (status::Ok, format!("Hello {}", name).as_str()) )); } let mut router = Router::new(); router.get("/", top_handler, "index"); router.get("/greet/:name", greet_handler, "greeting"); router.get("/to-top", redirect_handler, "to-top"); Iron::new(router).http("localhost:3000").unwrap(); println!("Listen on localhost:3000"); }
細かく見ていきましょう
Router
let mut router = Router::new(); router.get("/", top_handler, "index"); router.get("/greet/:name", greet_handler, "greeting"); router.get("/to-top", redirect_handler, "to-top");
この部分ではRouterを作成し、いくつかのルーティングを登録しています。
.get
の部分はHTTPメソッドを意味していて、.post
,.put
, .delete
のようにその他各種HTTPメソッドに対応しています。
引数はそれぞれ、マッチするURL, その時に呼び出されるハンドラ、ルーティングIDを定義しています。
ルーティングIDはそのルーティングを後から参照する際に利用できる識別子となっています。
URL
URL中では:param
のようにすることで、後からURLの一部を取得することができます。
また、*
を使うことでその部分は任意にマッチするようになります。
URLパラメータの取得
fn greet_handler(req: &mut Request) -> IronResult<Response> { let ref router = req.extensions.get::<Router>(); let ref name = router .unwrap() .find("name") .unwrap(); return Ok(Response::with( (status::Ok, format!("Hello {}", name).as_str()) )); }
このハンドラは/greet/:name
というURLにマッチしたときに呼び出されるようになっているハンドラです。
ハンドラ中で
let ref router = req.extensions.get::<Router>();
とすることでRouterを取得しています。extensions
はMiddlewareがリクエストを拡張するのに利用するもので、
今回の場合はRouterは自身をextensions
に保存しています。
ルータを通してURLのパラメータを取得することができます。find
メソッドにURLパラメータ名(この場合は"name"
)を指定すると
パラメータがOption
で手に入るので今回の場合は単純にunwrap
しています。
url_for
URL to-top
は、アクセスするとトップページにリダイレクトされるURLです。
ハンドラは以下のとおりです:
fn redirect_handler(req: &mut Request) -> IronResult<Response> { let ref top_url = url_for(req, "index", ::std::collections::HashMap::new()); return Ok(Response::with((status::Found, Redirect(top_url.clone())))) }
url_forを使うことでルーティングIDに対応するURLを取得することができます。
レスポンスにRedirect
を利用することでユーザーをリダイレクトすることができます。
まとめ
今回はRouter Middlewareを利用して複数のルーティングに対応したHTTPサーバーを実装しました。 また、url_forを利用してルーティング登録時に設定したルーティングIDからURLを取得することができます。
次回はテンプレートエンジンを利用してHTMLページの表示をやってみたいと思います。