概要
Sinatraをちょこちょこ使っていたのですがエラーハンドリングについて真面目に考えたことがなかったことがなく、これを機会にちゃんと学ぼうと思った。
目標
入力値エラーや、予期せぬエラーをAPIレスポンスとして返却する。
言語/フレームワーク
- ruby
- Sinatra
https://qiita.com/itaya/items/3626f79495dd05b83b4b
環境構築に関してはこちらの記事でまとめてるのでこれ参考にしてくださいー
ライブラリとしてactive_support
を使ってます。
理由は後で使う「空の判定」を楽に済ませるためです。必須ではないので使わない人はその部分は読み替えてください。
実装
前準備
まずベースとなるコードを紹介します。
require 'sinatra'
require 'sinatra/json'
require 'active_support/all'
get '/' do
data = {result: 'success'}
json data
end
実行すると{result: 'success'}
が返ってくるコードとなってます。
例外処理
ここに、入力値エラーを追加したいと思います。
エラーページ設定をOFFに
まず、現行のままだとエラーが発生した時点で標準のエラーページ
が表示されてしまうのでそれをOFFにします。
具体的にはshow_exceptionsというオプションをoffにします。
require 'sinatra'
require 'sinatra/json'
require 'active_support/all'
set :show_exceptions, false
get '/' do
data = {result: 'success'}
json data
end
例外の定義
既存の例外を使う場合は定義しなくてよいのですが、独自の例外を使いたい場合はそもそも定義する必要があります。(当たり前かもですけど自分は少しつまづきました...)
今回は入力値不正ように下記のような例外定義を追記します。
require 'sinatra'
require 'sinatra/json'
require 'active_support/all'
set :show_exceptions, false
class InvalidError < StandardError; end
get '/' do
data = {result: 'success'}
json data
end
例外を発生
そして、上記で定義した例外を発生させます。
今回はパラメータとしてkeyword
というものがなかった場合にエラーとします。
require 'sinatra'
require 'sinatra/json'
require 'active_support/all'
set :show_exceptions, false
class InvalidError < StandardError; end
get '/' do
raise InvalidError if params['keyword'].blank?
data = {result: 'success'}
json data
end
この状態でパラメータを指定しないでアクセスすると
こんな感じの初期エラーページとは違うものが表示されます。
例外をハンドリング
では、上記のエラーをハンドリングするようにしましょう。
例外のハンドリングはerror XXX do
の形式で書くことでハンドリングできます。
require 'sinatra'
require 'sinatra/json'
require 'active_support/all'
set :show_exceptions, false
class InvalidError < StandardError; end
get '/' do
raise InvalidError if params['keyword'].blank?
data = {result: 'success'}
json data
end
error InvalidError do
status 400
data = {result: '入力値不正'}
json data
end
このように書くことで、パラメータなしでアクセスすると{result: "入力値不正"}
このようにエラーのレスポンスが返ってきて、またステータスコードの方も400で返ってきてます!素晴らしい!
その他の例外をハンドリング
その他の例外をハンドリングしたい場合なのですが、いろいろな記事を見るとerror do
といった形で例外を指定しないと良いというように見えるのですが、これではExceptionしか拾ってくれません。
どういうことかというと
require 'sinatra'
require 'sinatra/json'
require 'active_support/all'
set :show_exceptions, false
class InvalidError < StandardError; end
get '/' do
nil.aaaa #エラーになるコード
raise InvalidError if params['keyword'].blank?
data = {result: 'success'}
json data
end
error InvalidError do
status 400
data = {result: '入力値不正'}
json data
end
error do
data = {result: '予期せぬエラー'}
json data
end
このようなコードを書いても、nil.aaaa
はキャッチしてもらえず、エラーのレスポンスではなくエラー画面が返ってしまいます。
そのため想定外のエラーを考慮するには
require 'sinatra'
require 'sinatra/json'
require 'active_support/all'
set :show_exceptions, false
class InvalidError < StandardError; end
get '/' do
nil.aaaa #エラーになるコード
raise InvalidError if params['keyword'].blank?
data = {result: 'success'}
json data
end
error InvalidError do
status 400
data = {result: '入力値不正'}
json data
end
error 500 do
data = {result: '予期せぬエラー'}
json data
end
このように500のステータスコードを指定すると良いでしょう。