qux = ->(env){ [200,{},['Hello world']] }
bar = ->(env){ qux.call(env) }
foo = ->(env){ bar.call(env) }
run foo
Slide 24
Slide 24 text
class Middleware
def initialize(app)
@app = app
end
def call(env)
@app.call(env)
end
end
Slide 25
Slide 25 text
class Reverse < Middleware
def call(env)
status, headers, body = super
body.each(&:reverse!)
[status, headers, body]
end
end
use Reverse
use Reverse
run ->(env){ [200,{},['Hello world']] }
Slide 26
Slide 26 text
Rack::Builder
and config.ru
Slide 27
Slide 27 text
$ rackup config.ru
Slide 28
Slide 28 text
if config.end_with?('ru')
Rack::Builder.new {
}.to_app
end
Slide 29
Slide 29 text
require_relative 'lib/my_app'
use Rack::CommonLogger
use Rack::Session::Cookie
run MyApp.new
Slide 30
Slide 30 text
map '/admin' do
use Authorization::Basic
run Admin::App.new
end
map '/api' do
use Authorization::Token
run Api::App.new
end
Slide 31
Slide 31 text
warmup do |app|
client = Rack::MockRequest.new(app)
client.get '/cached_resource'
end
Slide 32
Slide 32 text
rackup greeter.rb
Slide 33
Slide 33 text
if config.end_with?('rb')
require config
app_name = File.basename(config, '.rb')
app = Object.const_get(app_name.capitalize)
run app
end
Slide 34
Slide 34 text
class Greeter
def self.call(env)
params = Rack::Request.new(env).params
name = params.fetch('name', 'unknown')
[200, {}, ["Greetings, #{name}"]]
end
end
def call(env)
status, headers, body = @app.call
body = BodyProxy.new(body) do
# Ensure something happens after
# body.close is called, eg.
DB.connection.close
end
[status, headers, body]
end
use Rack::Sendfile
use ActionDispatch::Static
use Rack::Lock
use ActiveSupport::Cache::Strategy::LocalCache::Middleware
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
run Rails.application.routes
$ rake middleware
Slide 45
Slide 45 text
use Rack::Sendfile
use ActionDispatch::Static
use Rack::Lock
use ActiveSupport::Cache::Strategy::LocalCache::Middleware
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
run Rails.application.routes
$ rake middleware
Slide 46
Slide 46 text
Rails.application.routes
#=> ActionDispatch::Routing::RouteSet
def initialize
@set = Journey::Routes.new
@router = Journey::Router.new @set
end
def call(env)
req = ActionDispatch::Request.new(env)
@router.serve(req)
end
Slide 47
Slide 47 text
module ActionDispatch
class Request < Rack::Request
def initialize(env)
super
# ...
end
end
end
Slide 48
Slide 48 text
use Rack::Sendfile
use ActionDispatch::Static
use Rack::Lock
use ActiveSupport::Cache::Strategy::LocalCache::Middleware
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
run Rails.application.routes
$ rake middleware
Slide 49
Slide 49 text
use Rack::Sendfile
use ActionDispatch::Static
use Rack::Lock
use ActiveSupport::Cache::Strategy::LocalCache::Middleware
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
run Rails.application.routes
$ rake middleware
Slide 50
Slide 50 text
use Rack::Sendfile
use ActionDispatch::Static
use Rack::Lock
use ActiveSupport::Cache::Strategy::LocalCache::Middleware
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
run Rails.application.routes
$ rake middleware
Slide 51
Slide 51 text
More details about Rails on Rack:
http://guides.rubyonrails.org/rails_on_rack.html
• Supported by Passenger
• Supported by Unicorn (for responses < 30s)
• Supported by Puma
• WEBrick only supports partial hijacking
• Not supported by Thin (maybe?)
Slide 58
Slide 58 text
MyApp
Server
Internets Framework
Server Framework
Network Application
HIJACK
Rack
Slide 59
Slide 59 text
The future of Rack?
https://github.com/tenderlove/the_metal
https://gist.github.com/raggi/11c3491561802e573a47
https://github.com/Wardrop/Rack-Next