Rack
-
Upload
kerry-buckley -
Category
Technology
-
view
1.788 -
download
1
description
Transcript of Rack
Introduction to RackKerry Buckley, 26 October 2010
Introduction to Rack
Why was it needed?
How does it work?
Building a stack with middleware
Writing a simple rack application
Web frameworks
and many more…
Web servers
Mongrel
Webrick
CGI
Before Rack
With Rack
Rack-compliant interface
Introduction to Rack
Why was it needed?
How does it work?
Building a stack with middleware
Writing a simple rack application
Rack is just aninterface specification
A Rack app is…
• An object (not a class)…
• …which responds to call(env)…
• …and returns an array containing:
• response code
• a hash of headers
• the body**this is a slight simplification
The environment hash
• REQUEST_METHOD
• SERVER_NAME, SERVER_PORT
• SCRIPT_NAME, PATH_INFO, QUERY_STRING
• HTTP_ variables from request headers
• Some rack-specific variables
A simple Rack app
require 'rubygems'require 'rack'
class HelloWorld def call(env) [200, {"Content-Type" => "text/html"}, "Hello World!"] endend
Rack::Handler::Mongrel.run HelloWorld.new, :Port => 9292
require 'rubygems'require 'rack'
Rack::Handler::Mongrel.run proc { |env| [200, {"Content-Type" => "text/html"}, "Hello World!"]}, :Port => 9292
Even simpler Rack app
Revisiting the body
• An object (not a class)…
• …which responds to call(env)…
• …and returns an array containing:
• response code
• a hash of headers
• the body**this is a slight simplification
Revisiting the body
• Must respond to each, yielding strings
• Strings work in 1.8, but not 1.9
• close will be called if present
• to_path can provide a file location
Body as array
require 'rubygems'require 'rack'
class HelloWorld def call(env) [200, {"Content-Type" => "text/html"}, ["Hello ", "World!"]] endend
Rack::Handler::Mongrel.run HelloWorld.new, :Port => 9292
Body as IO object
require 'rubygems'require 'rack'
class HelloWorld def call(env) [200, {"Content-Type" => "text/html"}, StringIO.new("Hello World!")] endend
Rack::Handler::Mongrel.run HelloWorld.new, :Port => 9292
Body as self
require 'rubygems'require 'rack'
class HelloWorld def call(env) [200, {"Content-Type" => "text/html"}, self] end
def each yield "Hello " yield "World!" endend
Rack::Handler::Mongrel.run HelloWorld.new, :Port => 9292
The rackup file
• Configuration DSL for a Rack app
• Server-independent
• Allows stacking of middleware
• Provides simple route mapping
The rackup file
class HelloWorld def call(env) [200, {"Content-Type" => "text/html"}, "Hello World!"] endend
run HelloWorld.new
config_file = File.read(config)rack_application = eval("Rack::Builder.new { #{config_file} }")server.run rack_application, options
Your config.ru file:
Rack loads it like this:
The rack gem
Provides a bunch of helper classes
• Request/response wrappers
• Logging
• Authentication (basic and digest)
• Cookies and sessions
• Mock requests and responses
Introduction to Rack
Why was it needed?
How does it work?
Building a stack with middleware
Writing a simple rack application
Middleware
Middleware A
Middleware B
Application
Request
Request
Request
Response
Response
Response
Middleware
• A middleware is just a rack application
• Constructor takes next app down
• Can modify request or response
• Can call layer below, or just return
• Configured with ‘use’ in rackup file
Middleware in Rails
• Used internally for cookies, parameter parsing etc
• Add your own in environment.rb:
Rails::Initializer.run do |config| config.middleware.use "MyMiddlewareClass" end
Introduction to Rack
Why was it needed?
How does it work?
Building a stack with middleware
Writing a simple rack application
Demo!