Rack
...or how to build your own Ruby on Rails
by Hubert Łępicki
@hubertlepicki

What is Rack?
Rack: a Ruby Webserver Interface
Rack provides a minimal interface between webservers supporting Ruby and Ruby frameworks.
Before Rack
remember "apache proxy to cluster of mongrels"?
Different solutions
- (F)CGI
- mod_rails
- mongrel handler
- apache proxy + cluster of mongrels
- meanwhile, Python already had WSGI

Supported servers
- Apache/Passenger
- Nginx/Passenger
- Puma
- Unicorn
- Webrick ;)
- Thin
- Rainbows
- name it!
The interface
describe 'rack interface' doit 'should respond to call and accept hash'it 'should return [status, headers, and chunks of body]'end
Interface as lambda
lambda do |env|body = "Hello, World!"[ 200,{ "Content-Type" => "text/plain","Content-Length" => body.length.to_s },[body]]end
Interface as an object
class RackAwesomeMiddlewaredef call(env)body = "Rack is awesome!"[ 200,{"Content-Type" => "text/plain","Content-Length" => body.length.to_s},[body]]endend
Stack of middleware
Rackup file config.ru
use Rack::Reloader, 0 use Rack::ContentLength app = proc do |env|[ 200, {'Content-Type' => 'text/plain'}, ["a"] ]end run app$ rackup config.ru # starts the app
Interacting with layers below (above?)
class AwesomeMiddlewaredef initialize app@app = appenddef call(env)@app.call envendend
Modify the response of other layer
class AwesomeMiddlewaredef initialize app@app = appenddef call(env)res = @app.call(env)res[1]["Server"] = "Awesome Server"resendend
Modify environment
class AwesomeMiddlewaredef initialize app@app = appenddef call(env)env["RAILS_ENV"] = 'awesome'@app.call envendend
Rails on Rack
require ::File.expand_path('../config/environment', __FILE__)run Rails.application
Rails on Rack
# config/environments/staging.rbconfig.middleware.insert_before(::Rack::Runtime,"::BasicAuthMiddleware", "Staging") do |u, p|u == 'secret' && p == 'password'end
Configuring Rack middleware
class ConfigurableMiddlewaredef initialize(app, &block)config = OpenStruct.newyield config...endend# confug.ru / config/environments/*.rbconfig.middleware.use 'ConfigurableMiddleware' do |config|config.foo = 'bar'end
Examples
Rack::Lint
Rack::Cache
Rack::Logger
Rack::Static
Rack::Auth::Basic
Rack::TimeZone
Rack::Locale
Rack::Profiler
Faye
websocket-rack
Rails middleware stack
use Rack::Sendfile
use ActionDispatch::Static
use Rack::Lock
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 MyApp::Application.routes Links and stuff
"Rails on Rack" in Rails guides
http://guides.rubyonrails.org/rails_on_rack.html
"Build your own framework with Rack"
http://isotope11.com/blog/build-your-own-web-framework-with-rack-and-ruby-part-1
"Introduction to Rack middleware"
http://www.amberbit.com/blog/2011/07/13/introduction-to-rack-middleware/
Rack
By Hubert Łępicki
Rack
- 1,743