Sinatraのエラーハンドリング

Sinatraには not_foundハンドラとerrorハンドラの2つのハンドラが用意されています。
not_foundハンドラは404エラーを補足するためのエラーハンドラです。
errorハンドラは様々なエラーを補足するためのエラーハンドラです。

Not Foundハンドラ

not_foundハンドラは404エラーを補足するためのエラーハンドラです。
Sinatra::NotFoundが発生したとき、またはステータスコードが404のときは not_foundハンドラが実行されます。

1
2
3
not_found do
'This is nowhere to be found.'
end

Errorハンドラ

errorハンドラは様々なエラーを補足するためのエラーハンドラです。
例外オブジェクトにはRack変数の sinatra.error でアクセスできます。

1
2
3
error do
'Sorry there was a nasty error - ' + env['sinatra.error'].message
end

以下の設定をすると、environmentがDevelopmentのときにブラウザにスタックトレースを表示することができます。

1
set :show_exceptions, :after_handler

エラー固有の制御もできます。
MyCustomeErrorのエラーハンドリングをしたいときは以下のように定義します。

1
2
3
error MyCustomError do
'So what happened was...' + env['sinatra.error'].message
end

raiseでエラーを発生させるようにしてみます。

1
2
3
4
5
6
7
get '/' do
raise MyCustomError, 'something bad'
end

# 以下のようにレスポンスが返ります。

So what happened was... something bad

ステータスコードを指定してエラーハンドリングを行う方法もあります。

1
2
3
error 403 do
'Access forbidden'
end

レンジの指定も可能です。

1
2
3
error 400..510 do
'Boom'
end

errorハンドラにerrorコードを指定しなかった場合は何を補足するのか

errorハンドラにerrorコードを指定しなかった場合は、Exceptionを補足します。

1
2
3
4
5
6
7
def error(*codes, &block)
args = compile! "ERROR", /.*/, block
codes = codes.map { |c| Array(c) }.flatten
codes << Exception if codes.empty? #errorコードの指定がない場合
codes << Sinatra::NotFound if codes.include?(404)
codes.each { |c| (@errors[c] ||= []) << args }
end

https://github.com/sinatra/sinatra/blob/939ce04c1b77d24dd78285ba0836768ad57aff6c/lib/sinatra/base.rb#L1287

その他の例外は補足しません。
例えばExceptionのサブクラスであるStandardErrorは拾ってくれません。
ですので、明示的にerrorコードを指定しておいたほうがよいです。

1
2
3
error 500 do
'Sorry there was a nasty error - ' + env['sinatra.error'].message
end

参考文献