LoginSignup
9
9

More than 5 years have passed since last update.

Mojoliciousアプリ全体のエラー処理をする

Last updated at Posted at 2014-04-11

developmentモードでスクリプトエラーが起こった場合、
以下の様な画面が表示される。

スクリーンショット 2014-04-11 18.51.22.png

Mojolicious側でアプリの全体的なエラーをキャッチして、
このようなエラー画面を表示させている。
内部では、around_dispatchというフックを使って処理している。

独自にアプリ全体のエラーをキャッチして、
何かしらの処理したい場合も around_dispatch を使う。

(強力なフックなので気軽に使うべきではないと、
ドキュメントで注意されているのでちょっとこわい)

例えば、アプリのエラーメッセージに、
「SYSTEM ERROR!!」というプレフィクスを付けたいとすると、
以下のような設定になる。

myapp.pl
app->hook(around_dispatch => sub {
    my ($next, $c) = @_;
    eval { $next->(); 1; };

    # アプリにエラーが起こった場合
    if ($@) {
        $c->app->log->fatal('SYSTEM ERROR!!: '.$@);
        die $@;
    }
});

これで、ログにエラーメッセージを出しつつ、
通常通りのエラー画面がブラウザに表示されるようになる。

around_dispatchについて

デフォルトで around_dispatch で設定されている処理は以下のもの。

  • エラー処理(Mojolicious::_exception)
  • ディスパッチ処理(Mojolicious::dispatch)

前節の設定を行うと、この2つの処理の間に入ることになる。
つまり、

エラー処理

独自エラー処理

ディスパッチ処理

の順番で、実行されていく。
各処理中に「$next->()」を呼び出すことにより、
次の処理を実行する。

前節の設定で「$next->()」という記述があったが、
これは「ディスパッチ処理の実行」を意味していた。

また、Mojolicious::_exceptionの内容は以下のようになっている。

lib/Mojolicious.pm
sub _exception {
  my ($next, $c) = @_;
  local $SIG{__DIE__}
    = sub { ref $_[0] ? CORE::die($_[0]) : Mojo::Exception->throw(@_) };
  $c->render_exception($@) unless eval { $next->(); 1 };
}

_exceptionの中でも、「$next->()」が記述されている。
これは、前節で設定した処理を実行していることになる。

このように、「$next->()」を呼び出すことによって、
連続的に次の処理を呼び出す形になっている。
「$next->()」をしなかった場合は、処理が止まってしまうので注意。

結構重要な処理がこのフックで呼ばれているので、
触らずに済むなら触らないようにしたい。

9
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9