Railsで例外が発生し、かつApplicationControllerとかで拾われない場合、通常は設定された exceptions_app ( デフォルトだと ActionDispatch::PublicExceptions
) が呼ばれてエラー画面表示の処理が行われる
application/html がcontent-typeに指定されてると public/500.html
とか public/404.html
とかを返してくれるけど、htmlじゃない場合はある規定された形のhashに対して to_xxx
したものをbodyとして返すだけになってしまい、こちらが定めた定形のメッセージを返そうとした際に少し不便になる
実際に public/500.html
を返すMiddlewareはどうなっているかというと以下の通りになっている
rails/public_exceptions.rb at 4dcb46182a4aaa57f44f3eb722c1db54fa0ff843 · rails/rails · GitHub
今回はこれの各種 content-type 対応版を書いた
まだgemにはしてないが以下の通り (というか既に存在しそうだし)
class MimeTypePublicExceptions < ActionDispatch::PublicExceptions private def render(status, content_type, _body) ext = content_type.symbol || 'html' # symbolは拡張子を表すメソッドではない path = [ "#{public_path}/#{status}.#{I18n.locale}.#{ext}", "#{public_path}/#{status}.#{ext}" ].find { |fp| File.exist?(fp) } if path render_format(status, content_type, File.read(path)) else [404, { 'X-Cascade' => 'pass' }, []] end end end
こんなかんじでつかう
Rails.application.configure do config.exceptions_app = lambda do |env| MimeTypePublicExceptions.new(Rails.public_path).call(env) end end
おわり