10分でわかる Rack ミドルウェアの作り方

先週から今日まで2週間アメリカ旅行をしていた伊藤です。
サンフランシスコで日本時間のチームとリモートワークをしてみた感想は別の記事で書こうと思っています。

Rack::ErrorToSlack

先日 hitode909 さんの ローカルサーバーでエラーが出たら即座にSlackに投稿するPlackミドルウェア という記事を拝見したのですが、ちょうどその時に社内でもサーバーサイドエンジニアとフロントエンドエンジニアが密な関係で開発を進めていたプロジェクトがあり、これは便利そうだね!と話題に上りました。
ということで早速 Rails でそれと同じような動作をする Rack ミドルウェア rack-error_to_slack を書いてみました。恥ずかしいことに今まで Rack がそもそも何なのかよくわかっていませんでしたが、先人たちがインターネット上に知見を残しておいてくれたおかげで半日ぐらいで作成することができました。今回はエラーハンドリングをする Rack ミドルウェアの作成方法をまとめてみようと思います。

(2分経過)

Rack ミドルウェアの基本

Rack ミドルウェアとは何かについては Ruby Freaks Lounge:第25回 Rackとは何か(3)ミドルウェアのすすめ で丁寧に説明がされているため、こちらがオススメです。

この記事を読むのに必要な時間:およそ 3 分

と書かれているので、3分で読み終わってください!

上の記事にも簡単に書かれていましたが、Rack ミドルウェアのミニマムな形は以下のようになります。

1
2
3
4
5
6
7
8
9
10
11
class Foo
def initialize(app)
@app = app
end

def call(env)
res = @app.call(env)
# do something
res
end
end

この形を元に、あとは自分のやりたいような処理を加えるだけなので、簡単ですね!
#do something 部分の具体例を知りたい方は、以下の記事に簡単な例がありましたので参考にしてみてください。

(7分経過)

Rack ミドルウェアでエラーハンドリング

残りの3分で、他の記事では見かけなかったエラーハンドリングの方法を紹介します。

Airbrake という、エラーログを見やすい形で蓄積するサービスがありますが、そのgem も Rack アプリケーションとして作られていて、そのミドルウェア部分(この辺り)でエラーハンドリングをしています。他にはエラーメッセージを見やすい形で表示する charliesome/better_errors もミドルウェア部分(この辺り)でエラーハンドリングをしていたので、その実装を参考にしました。
といっても難しいことはしておらず、今回作成した rack-error_to_slack では以下のようにエラーハンドルしています。

1
2
3
4
5
6
def call(env)
@app.call(env)
rescue Exception => exception
Message.new(env, exception.message).send #Slackにメッセージ送信
raise exception
end

Exception が渡されてきたら、自分の行いたい処理を行って、その Exception を次のレイヤーにも渡してあげるだけです。

最後に少し注意したいのが、例えば Rails で WebAPI を作る時に以下のように Rails 側でエラーハンドルする場合です。このようにしてしまうと Rack ミドルウェアまで Exception が渡されなくなってしまうので気をつけましょう。

1
2
3
4
5
6
7
class ApiController < ApplicationController
rescue_from Exception, with: :render_500

def render_500
render json: { status: 500, message: 'Internal Server Error' }
end
end

自分もまだ Rack の触りだけしか理解していないので、もし間違いがあれば @showwin までご連絡いただければと思います。

(10分経過!?)

Ruby on Railsを活用したWebサービスや業務システム開発をご検討の企業様は、是非MMMにご相談下さいませ!

このエントリーをはてなブックマークに追加