LoginSignup
10
9

More than 5 years have passed since last update.

Rack

Posted at

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 を書く

config.ru
run lambda { |env| [200, { "Content-Type" => "text/html" }, ["Hello,world"]] }

2. rackup コマンドで起動

$ rackup config.ru

3. ブラウザからアクセス

$ curl http://localhost:9292/

Rackの規約

  1. 引数を1つ(仮引数名は慣習的にenv)をもつ call メソッドを実装する
  2. call メソッドは、[status, header, body] を返すこと

Rack Middleware

サーバとフレームワークの間で実行したい処理を定義する。

Middlewareの規約

  1. 1番目の引数に app を受け取る initialize メソッドを定義する
  2. Rackの規約を満たす call メソッドを定義する

フィルタのようにミドルウエアを組み合わせて使う。
一般的に use を使ってミドルウェアを呼び出す。
以下の例だと、A -> Bの順番に Middleware が呼び出される

config.ru
use A
use B
run App

rack標準で提供されるMiddleware

  • Rack::Lobster
  • Rack::File
  • Rack::Auth::Basic
  • Rack::Auth::Digest::MD5

など

rails と rack

rails が rack をどのように使っているかを探ってみる。rails は抽象化されているため複雑だが、規約を意識すればそれほど難しくはない(と思う)。

今回調べたバージョンは 4.2.5.1

今回必要なのは railties と actionpack。

また、Railsアプリを作成しておく。

Railsアプリ -> Rack

4.2 の config.ru では、config/environment.rb を読み込み、Rails.application を rackup する

config.ru
run Rails.application

config/environment.rb の中で、 config/application.rb を読み込み、アプリケーションを初期化(Rails.application.initialize!)している。

config/environment.rb
# 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 を継承している。

config/application.rb
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 に渡されるようだ。

10
9
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
10
9