Mojoliciousですべての処理の前に実行する処理をアンダーで記述する

たとえば認証などを行う場合は、すべての処理の直前で、ログインしているかどうかを確認したいと思います。このような場合はアンダーという機能を利用します。ルートからunder()でアンダーを作成して、実行したいコールバックを指定します。コールバックの戻り値が、真の場合は続きの処理を行い、偽の場合は続きの処理を行いません。

sub startup {
  my $self = shift;
  
  my $r = $self->routes;

  # 認証
  $r = $r->under(sub {
    my $self = shift;
    
    if ($self->session('login_name')) {
      return 1;
    }
    else {
      my $url = $self->req->url->to_string;
      if ($url =~ m#login$#) {
        return 1;
      }
      else {
        $self->render('denied');
        return;
      }
    }
  });

  $r->get('/')->name('index');
}

少し変な記述に見えますが、toメソッドがアンダー自体を返すので上記のような書き方が簡潔だと思います。すべてのルートでアンダーを共有するので、$r自体を上書きしてしまっています。セッションIDが発行されていない場合でログインを行うためのURL以外にアクセスした場合は、認証が拒否の知らせるテンプレートを描画するようにしています。

Mojolicious 6からの変更点

Mojolicious 6からは、ブリッジを作成するbridgeメソッドが、underメソッドに統合されています。機能は同じなので、underメソッドを使うようにしてください。

関連情報