2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ItayaAdvent Calendar 2022

Day 12

Sinatraでエラーハンドリングをしてみよう

Last updated at Posted at 2022-12-11

概要

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に

まず、現行のままだとエラーが発生した時点で標準のエラーページ
スクリーンショット 2022-12-10 23.27.27.png
が表示されてしまうのでそれを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  

この状態でパラメータを指定しないでアクセスすると

スクリーンショット 2022-12-10 23.33.59.png

こんな感じの初期エラーページとは違うものが表示されます。

例外をハンドリング

では、上記のエラーをハンドリングするようにしましょう。
例外のハンドリングは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で返ってきてます!素晴らしい!
スクリーンショット 2022-12-10 23.37.14.png

その他の例外をハンドリング

その他の例外をハンドリングしたい場合なのですが、いろいろな記事を見ると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のステータスコードを指定すると良いでしょう。

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?