Rackとは

ついこの間まで「名前は聞いたことあるけど結局Rackってなんなんだろう」状態だった自分

最近仕事で触らなきゃいけなくなったので重い腰を上げてきちんと調べてみました

Rackってなんだ?

rackのロゴ

Rackってなんだ?と聞かれてめっちゃシンプルに答えるなら、RackはRubyのオブジェクトです

HTTP Request / ResponseをラップしてwebサーバーとwebアプリケーションのAPIを単一のメソッドに統合することで、両者のインターフェースとしての役割を果たします (<= ここ早口)

Rubyのオブジェクトなので、具体的にはRubyのwebアプリケーションフレームワーク (Ruby on RailsやSinatora)とwebサーバーとの橋渡しを行います

サーバーとアプリケーションとの橋渡しって?

webアプリケーションはwebサーバーの上で動いています

webのリクエストはまずはipアドレスでwebサーバーを特定し、さらにwebアプリケーションが動いているポートに到達するところから始まります

そして当たり前ですがwebアプリケーションはRequestを受けてなんらかの処理を行い、最後にResponseを返します

Rackはそのwebサーバー => webアプリケーション、webアプリケーション => webサーバーの間で処理を行います

httpリクエストがwebサーバーに到達してからwebアプリケーションに送られ、httpレスポンスがwebアプリケーションで生成された上でwebサーバーから返される図

RailsでRackが動いているのを確認する

railsでは以下のコマンドで設定されているrack middlewareを確認することができます

$ bundle exec rails middleware

rails newでtest-appというアプリケーションを作って確認していみるとざっとみただけで20くらいのmiddlewareが動いていました

その中にあるRack::xxxxがRackと呼ばれているもので、7つくらいいました

一番下にあるApplication (今回はtest-appという名前でrails newしたのでTestApp::Application.routes)がRailsアプリケーションです

Requestが送信されてきたときはmiddlewareの上から順番に処理をしていき、一番下のwebアプリケーションに到達します

逆にResponseを返すときはwebアプリケーションから始まり上へ向かって処理を進めていきます

rails middlewareの実行結果のキャプチャと、Requestでは上から下、Responseでは下から上へmiddlewareが実行されると説明した図

余談ですが複数人で開発してるとちょくちょくぶつかるActiveRecord::PendingMigrationErrorはmiddlewareでやってるからサーバー起動時には起こらないんですね

ActiveRecord::Migration::CheckPendingが間くらいにいました

Rack ファイルの中身

Rack ファイルという名前が正しいかはわからないですが、Rackで行う処理を自前で実装する場合、rackのルールに従う必要があります

  • 次のRack層にenvを渡してあげる
  • 値を返すときは[status, header, body]の構成のArrayにする

今回はリクエストを受け取ってhello worldを出力し、そのまま次の層へリクエストを渡すだけの動きにしています

class Rack::Hoge
  def initialize(app)
    @app = app
  end

  # callメソッドがenvを引数にとるのはRackのルール
  def call(env)
    puts 'hello world
    @app.call(env) # initializeしたappのcallを呼ぶことで次の層のRack (or middleware)を呼び出す
 end
end

これをconfig/application.rbで追加します

config/application.rb

module TestApp
  class Application < Rails::Application
    config.load_defaults 5.2

    config.middleware.use Rack::Hoge # <=ここで追加
  end
end

この状態でもう一度$ bundle exec rails middlewareを実行すると、Applicationの直前にRack::Hogeが入ります

rails middlewareの実行結果の下から2行目、TestApp::Application.routesの上に追加したRack::Hogeが入っている図

この状態でrails serverを起動しルートにアクセスすると、リクエストが発生してRack::Hogeが実行されhello worldという文字がコンソールに表示されます

rails サーバーのログにhello worldと表示されている図

まとめ

「Rack聞いたことある」状態から「Rack知ってる」状態まではいけた気がしてます

middlewareってあんま触ったことないから結構勉強になった

ただmiddlewareの設定までrailsのconfigの中でしてるのはいいのか?と思います (いいのかな、まあいいのか)

参考

leah blogs: Introducing Rack

第23回 Rackとは何か(1)Rackの生まれた背景:Ruby Freaks Lounge|gihyo.jp … 技術評論社

Rails と Rack - Railsガイド

GitHub - rack/rack: a modular Ruby webserver interface

rack/SPEC.rdoc at master · rack/rack · GitHub