me
5th year SE/CS
bills fan
ruby fanatic
gemcutter lead
Slide 3
Slide 3 text
this talk is about
internets
rubies
unicorns
Slide 4
Slide 4 text
HTTP
Slide 5
Slide 5 text
history
Slide 6
Slide 6 text
tim berners-lee
Slide 7
Slide 7 text
the first web server
Slide 8
Slide 8 text
No content
Slide 9
Slide 9 text
http 1.0: rfc1945
http 1.1: rfc2616
Slide 10
Slide 10 text
No content
Slide 11
Slide 11 text
the protocol
request => response
stateless
Slide 12
Slide 12 text
requests:
Request line, such as GET /images/logo.gif
HTTP/1.1
Headers, such as Accept-Language: en
An empty line
An optional message body
Slide 13
Slide 13 text
verbs
HEAD
GET
POST
PUT
DELETE
etc...
Slide 14
Slide 14 text
response
code (200, 404, 500)
more headers
body
Slide 15
Slide 15 text
codes
Slide 16
Slide 16 text
200s
Slide 17
Slide 17 text
200s
200 OK
201 Created
202 Accepted
Slide 18
Slide 18 text
300s
Slide 19
Slide 19 text
300s
301 Moved Permanently
302 Found
304 Not Modified
Slide 20
Slide 20 text
400s
Slide 21
Slide 21 text
400s
401 Unauthorized
403 Forbidden
404 Not Found
418 I'm a teapot
Slide 22
Slide 22 text
RFC 2324 HTCPCP/1.0 1 April 1998
In practice, most automated coffee pots cannot
currently provide additions.
2.3.2 418 I'm a teapot
Any attempt to brew coffee with a teapot should
result in the error code "418 I'm a teapot". The
resulting entity body MAY be short and stout.
Slide 23
Slide 23 text
500s
Slide 24
Slide 24 text
500s
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
# config.ru
class Awesome
def call(env)
[200, {'Content-Type' => 'text/plain'}, 'AWESOME.']
end
end
run Awesome
Slide 44
Slide 44 text
middleware
think of pancakes
stack them up!
instead of run, use
mmm, pancakes
Slide 45
Slide 45 text
No content
Slide 46
Slide 46 text
class PassThrough
def initialize(app)
@app = app
end
def call(env)
@app.call(env)
end
end
Slide 47
Slide 47 text
I::Rack
def call(env)
if env["PATH_INFO"] == "/WMD"
[
404,
{"Content-Type" => "text/plain"},
"Not found"
]
else
@app.call(env)
end
end
Slide 48
Slide 48 text
Rack::Obama
def call(env)
if env["CONTENT_TYPE"] == "nobel-prize/peace"
[
202,
{"Content-Type" => "nobel-prize/peace"},
"Accepted"
]
else
@app.call(env)
end
end
Slide 49
Slide 49 text
Rack::Kanye
Slide 50
Slide 50 text
def call(env)
request_uri = env['REQUEST_URI']
if request_uri =~ /kanye=true/
env['REQUEST_URI'].gsub!("&kanye=true","")
@app.call(env)
else
req = "http://#{env['HTTP_HOST']}#{request_uri}&kanye=true"
[
302,
{'Location' => "http://kanyelicious.appspot.com/" + req },
'Redirecting...'
]
end
end
Slide 51
Slide 51 text
useful middlewares
Rack::Cache
Rack::Bug
Rack::Maintenance
too many to list !SLIDE @@@ text $ rake
middleware use Rack::Lock use
ActionController::Failsafe use
ActionController::Session::CookieStore, #
use
ActionController::ParamsParser use
Rack::MethodOverride use Rack::Head use
ActiveRecord::ConnectionAdapters::ConnectionM
use ActiveRecord::QueryCache run
ActionController::Dispatcher.new @@@
Slide 52
Slide 52 text
real world use:
Slide 53
Slide 53 text
maintenance mode
problem: serve gems when running long
migrations
rack promotes decoupled architectures
enable when tmp/maintenanance.txt exists
Slide 54
Slide 54 text
normally
# config.ru
run Rack::Adapter::Rails.new(:environment => ENV['RAILS_ENV'])
Slide 55
Slide 55 text
require File.join('vendor', 'bundler_gems', 'environment')
require File.join('config', 'environment')
use Rack::Static,
:urls => ["/index.html",
"/favicon.ico",
"/images",
"/stylesheets"],
:root => "public/maintenance"
use Hostess
use Rack::Maintenance,
:file => File.join('public', 'maintenance', 'index.html')
run Sinatra::Application