Rackについて
サーバとフレームワークを結ぶインタフェース
Web Server <---> Rack <---> Web Framework
Web Server
- WEBRick
- unicorn
- puma
Web Framework
- Ruby on Rails
- Sinatra
Quick Start
0. install
$ gem install rack
1. config.ru を書く
run lambda { |env| [200, { "Content-Type" => "text/html" }, ["Hello,world"]] }
2. rackup コマンドで起動
$ rackup config.ru
3. ブラウザからアクセス
$ curl http://localhost:9292/
Rackの規約
- 引数を1つ(仮引数名は慣習的に
env
)をもつcall
メソッドを実装する -
call
メソッドは、[status, header, body]
を返すこと
Rack Middleware
サーバとフレームワークの間で実行したい処理を定義する。
Middlewareの規約
- 1番目の引数に app を受け取る
initialize
メソッドを定義する - Rackの規約を満たす
call
メソッドを定義する
例
フィルタのようにミドルウエアを組み合わせて使う。
一般的に use
を使ってミドルウェアを呼び出す。
以下の例だと、A -> Bの順番に Middleware が呼び出される
use A
use B
run App
rack標準で提供されるMiddleware
- Rack::Lobster
- Rack::File
- Rack::Auth::Basic
- Rack::Auth::Digest::MD5
など
rails と rack
rails が rack をどのように使っているかを探ってみる。rails は抽象化されているため複雑だが、規約を意識すればそれほど難しくはない(と思う)。
今回必要なのは railties と actionpack。
また、Railsアプリを作成しておく。
Railsアプリ -> Rack
4.2 の config.ru では、config/environment.rb を読み込み、Rails.application を rackup する
run Rails.application
config/environment.rb の中で、 config/application.rb を読み込み、アプリケーションを初期化(Rails.application.initialize!)している。
# Load the Rails application.
require File.expand_path('../application', __FILE__)
# Initialize the Rails application.
Rails.application.initialize!
Rails.application.initialize! 内で、rack の Middleware の呼び出しを行っている(はずだ)。
config/application.rb では Rails::Application を継承したクラスを定義して設定を記述する。
なお、 Rails::Application は Rails::Engine を継承している。
require File.expand_path('../boot', __FILE__)
require 'rails/all'
Bundler.require(*Rails.groups)
module MyApp
class Application < Rails::Application
config.time_zone = 'Tokyo'
end
end
Railsライブラリの内部を探る
rails が呼び出している Middleware については、rakeコマンドで表示できる。
$ rake middleware
use ...
run MyApp::Application.routes
MyApp::Application.routes は Rails::Engine クラス内で定義された メソッド Rails::Engine#routes であり、ActionDispatch::Routing::RouteSet のインスタンスを保持している。
ActionDispatch::Routing::RouteSet クラスでは call が定義されており、
その中で、Journey::Router#serve が呼ばれている。
このメソッドは、[status, headers, body]
を返しており、ここから rack に渡されるようだ。