問題点
この問題は Mojoliciousでhttps(SSL)専用ページとhttp専用ページの振り分けをroutesのbridgeを使って行うを実装した時に起こる問題です。
件のエントリーの実装でもスタンドアロンのサーバで公開する場合には問題にならないのですが、Nginx等のリバースプロクシの後ろにアプリケーションサーバを置いて運用する場合に問題が起きます。
通常、webサーバであるNginxとクライアントの間ではSSL通信を行い、バックエンドのアプリケーションサーバ(Starman等)とNginxの間では通常のhttpで通信すると思います。
SSL通信
クライアント --- Nginx
| http通信
Starman
この場合だと、件のエントリーの
# 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;
}
);
ようにschemeで判定してhttps~にリダイレクトする場合、Nginxとアプリケーションは常にhttpで通信しているのでリダイレクトが無限ループしてしまいます。
Nginxとアプリケーション間をSSLにすればよいのですが、(アプリケーション側の)ポートを開けたり指定しなくてはならなくなったりと色々面倒なことになりそうです...。
対策
Nginxの設定でリダイレクトを使うか、SSLの場合はリンクをhttpsで指定するかしか無さそう。
例えばstartupの中で下記のようなhelperを定義して、
# helper method
$self->helper(
url_for_http => sub {
my $self = shift;
my $url = $self->url_for(@_)->to_abs->scheme('http');
return $url;
}
);
$self->helper(
url_for_https => sub {
my $self = shift;
my $url = $self->url_for(@_)->to_abs->scheme('https');
return $url;
}
);
templateで
<%= link_to url_for_http('/') => begin %>httpを強要<% end %>
<%= link_to url_for_https('/ssl_onry') => begin %>セキュアなページへのリンク<% end %>
のように使うしか無いのかな。