Mojoliciousでhttps(SSL)専用ページとhttp専用ページの振り分けをroutesのbridgeを使って行う

Mojoliciousでhttps(SSL)専用ページとhttp専用ページの振り分けをroutesのbridgeを使って行う

このエントリーには問題点があります(2013/5/5追記)

webアプリを作る上でセキュアな通信を強要するページとそうではないページを振り分けるにはどうすればいいのか悩んでいたのだけど、ルーターでリダイレクトさせる方法にしてみた。

全てのページをSSLでアクセスされても速度的にとか負荷的に困るので、ある決まったrouteのみSSLでアクセスして、メインのコンテンツは通常のhttp通信(非SSL)にredirectする仕様。

必ずhttpsでアクセスするルート
  • /login
  • /join
必ずhttpでアクセスするルート
  • /
  • /entry/1
  • /entry/2
  • /entry/....
httpでもhttpsでもいいルート
  • /mypage
  • /favorite/list/1

例ではログインページや登録ページではセキュアな通信をして、トップページとエントリーページは普通のhttpで通信する。httpsでもhttpでもどちらでもいいページは最後の Any routes の所で振り分けられる。

sub startup {
  $self = shift;
....

  # Routes
  my $routes = $self->routes;

  # SSL onry routes
  my $ssl_rotes = $routes->bridge->to(
    cb => sub{
      my $self = shift;

      my $req = $self->req;
      return 1 if $req->is_secure;
      
      $self->redirect_to($req->url->to_abs->scheme('https'));
      return;
    }
  );
  # スッキリ書くならこんな感じ?
  # my $ssl_rotes = $routes->bridge->to(
  #   cb => sub{
  #     return 1 if $_[0]->req->is_secure;      
  #     $_[0]->redirect_to($_[0]->req->url->to_abs->scheme('https'));
  #     return;
  #   }
  # );
  # Not SSL routes
  my $not_ssl_routes = $routes->bridge->to(
    cb => sub{
      my $self = shift;
      
      my $url = $self->req->url;
      return 1 if $url->base->scheme eq 'http';
      
      $self->redirect_to($url->to_abs->scheme('http'));
      return;
    }
  );

  # SSL onry route
  $ssl_rotes->route('/login')->to('login#index');
  $ssl_rotes->route('/join')->to('join#index');

  # not SSL routes
  $not_ssl_routes->route('/')->to('top#index');
  $not_ssl_routes->route('/entry/:id', id => qr/\d+/)->to('entry#index', id => 1 );

  # Any Routes
  $routes->route('/:controller')->to(action => 'index');
  $routes->route('/:controller/:action')->to();
  $routes->route('/:controller/:action/:id')->to();
}

考えついたのはこんな感じのコードだけど、もっといい方法があるかもしれません。知っている方いたら教えて下さい!