Featured image of post 第10回-URLで振り分けよう - Mooを使ってディスパッチャーを作ってみよう

第10回-URLで振り分けよう - Mooを使ってディスパッチャーを作ってみよう

URLパターンでハンドラーを振り分ける機能を追加します。正規表現マッチングを使った、より実践的なルーティングの仕組みを学びましょう。

@nqounetです。

前回は、アクション名から自動でハンドラーを生成する仕組みを作りました。

今回は、URLパターンでハンドラーを振り分ける機能を追加します。

問題:単純な名前だけでは足りない

これまではlistformのような単純な名前でハンドラーを選んでいました。しかし、実際のWebアプリケーションでは、URLパターンで振り分けたい場面が多くあります。

例えば:

  • /posts → 投稿一覧
  • /posts/123 → 投稿ID 123の詳細
  • /posts/new → 新規投稿フォーム

URLの形式を見て、適切なハンドラーを選ぶ仕組みが必要です。

解決策:正規表現でURLパターンをマッチング

URLパターンと対応するハンドラーを登録し、正規表現でマッチングする仕組みを作ります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package Router {
    use Moo;

    has routes => (
        is      => 'ro',
        default => sub { [] },
    );

    sub add_route {
        my ($self, $pattern, $handler) = @_;
        push @{$self->routes}, {
            pattern => $pattern,
            handler => $handler,
        };
    }

    sub match {
        my ($self, $path) = @_;
        for my $route (@{$self->routes}) {
            my $pattern = $route->{pattern};
            if ($path =~ /^$pattern$/) {
                return $route->{handler};
            }
        }
        return undef;  # マッチしなかった
    }
};

add_routeでURLパターン(正規表現)とハンドラーを登録し、matchでパスに一致するハンドラーを探します。

使ってみよう

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# ルーターを作成
my $router = Router->new;

# ルートを登録
$router->add_route('/posts',        ListHandler->new);
$router->add_route('/posts/new',    FormHandler->new);
$router->add_route('/posts/(\d+)',  DetailHandler->new);

# マッチングしてハンドラーを取得
my $handler = $router->match('/posts');      # ListHandler
$handler->run if $handler;

$handler = $router->match('/posts/123');     # DetailHandler
$handler->run if $handler;

$handler = $router->match('/unknown');       # undef(マッチしない)
warn "Not Found" unless $handler;

URLの形式に応じて、適切なハンドラーが選ばれるようになりました。

	flowchart LR
    P["/posts/123"]
    R[Router]
    M{マッチング}
    L["/posts" → List]
    F["/posts/new" → Form]
    D["/posts/(\d+)" → Detail]
    H[DetailHandler]
    
    P --> R
    R --> M
    M -->|"順番に試す"| L
    M -->|"順番に試す"| F
    M -->|"マッチ!"| D
    D --> H

まとめ

  • URLパターンでハンドラーを振り分ける仕組みをルーターと呼ぶ
  • 正規表現を使ってURLパターンをマッチングする
  • add_routeでパターンとハンドラーを登録する
  • matchでパスに一致するハンドラーを探す

次回予告

次回は、これまで作ってきた機能を統合し、完成したディスパッチャーをBBSに組み込みます。いよいよ完成です。お楽しみに。

comments powered by Disqus
Hugo で構築されています。
テーマ StackJimmy によって設計されています。