8 Minutes On Rack

26,083 views

Published on

From Ruby Manor 2008

Published in: Technology
2 Comments
24 Likes
Statistics
Notes
No Downloads
Views
Total views
26,083
On SlideShare
0
From Embeds
0
Number of Embeds
82
Actions
Shares
0
Downloads
216
Comments
2
Likes
24
Embeds 0
No embeds

No notes for slide

8 Minutes On Rack

  1. 1. 8 minutes on Rack Dan Webb (dan@danwebb.net)
  2. 2. Web Framework
  3. 3. Web Server
  4. 4. Library
  5. 5. A Convention
  6. 6. If you have a Ruby object...
  7. 7. that has a call method which takes one argument... app.call(env)
  8. 8. and that method returns an array with 3 elements... [200, { 'Content-Type' => 'text/plain' }, 'Hello World!']
  9. 9. then you can connect it to any web server that supports Rack require 'thin' Rack::Handler::Thin.run(app, :Port => 4000)
  10. 10. and you've got yourself a web application
  11. 11. Fin
  12. 12. app = Proc.new do |env| [200, { 'Content-Type' => 'text/plain' }, 'Hello World!'] end require 'rubygems' require 'thin' Rack::Handler::Thin.run(app, :Port => 4000)
  13. 13. class HelloWorld def initialize(name) @name = name end def call(env) [200, { 'Content-Type' => 'text/plain' }, "Hello #{@name}!"] end end require 'rubygems' require 'rack' Rack::Handler::Mongrel.run(HelloWorld.new("Dan"), :Port => 4000)
  14. 14. // Courtesy of Pratik Naik! #include "ruby.h" VALUE method_call(VALUE self, VALUE env) { VALUE response = rb_ary_new(); VALUE headers = rb_hash_new(); rb_hash_aset(headers, rb_str_new2("Content-Type"), rb_str_new2("text/plain")); rb_ary_push(response, INT2NUM(200)); rb_ary_push(response, headers); rb_ary_push(response, rb_str_new2("Hello World!")); return response; } void Init_rock() { VALUE Rock = rb_define_class("Rock", rb_cObject); rb_define_method(Rock, "call", method_call, 1); } // run.rb require 'rock' require 'thin' Rack::Handler::Thin.run Rock.new, :Port => 4000
  15. 15. def call(env)
  16. 16. { "SERVER_NAME"=>"localhost", "HTTP_ACCEPT_ENCODING"=>"gzip,deflate", "HTTP_USER_AGENT"=>"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en- GB; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4", "PATH_INFO"=>"/", "SCRIPT_NAME"=>"", "SERVER_PROTOCOL"=>"HTTP/1.1", "HTTP_ACCEPT_LANGUAGE"=>"en-gb,en;q=0.5", "HTTP_HOST"=>"localhost:4000", "REMOTE_ADDR"=>"127.0.0.1", "HTTP_KEEP_ALIVE"=>"300", "REQUEST_PATH"=>"/", "SERVER_SOFTWARE"=>"thin 0.8.2 codename Double Margarita", "HTTP_ACCEPT_CHARSET"=>"ISO-8859-1,utf-8;q=0.7,*;q=0.7", "HTTP_VERSION"=>"HTTP/1.1", "REQUEST_URI"=>"/", "SERVER_PORT"=>"4000", "QUERY_STRING"=>"", "GATEWAY_INTERFACE"=>"CGI/1.2", "HTTP_ACCEPT"=>"text/html,application/xhtml+xml,application/xml;q=0.9, */*;q=0.8", "HTTP_CONNECTION"=>"keep-alive", "REQUEST_METHOD"=>"GET" }
  17. 17. [200, { 'Content-Type' => 'text/plain' }, "Hello #{@name}!"] Status Code
  18. 18. [200, { 'Content-Type' => 'text/plain' }, "Hello #{@name}!"] HTTP Headers
  19. 19. [200, { 'Content-Type' => 'text/plain' }, "Hello #{@name}!"] Response Body
  20. 20. Response body can be any object that respond_to?(:each) file = File.new('myfile.xml') [200, { 'Content-Type' => 'application/xml' }, file]
  21. 21. class StreamingFile def initialize(file) @file = file end def length File.size(@file) end def last_modified File.mtime(@file).rfc822 end def each File.open(@file, "rb") do |file| while part = file.read(8192) yield part end File.delete(@file) end end
  22. 22. [200, { 'Content-Type' => 'audio/mp3', 'Content-Length' => file.length.to_s }, file]
  23. 23. Duck typing! • Streaming • Clean up after response sent • Complex responses • Loads more...
  24. 24. Why?
  25. 25. Common interface
  26. 26. • Passenger • Mongrel • CGI • SCGI • FastCGI • Thin • Ebb • Fuzed • Webrick • Litespeed
  27. 27. Write once, serve however...
  28. 28. Convienient way to write micro apps
  29. 29. Example: Development Server
  30. 30. class StaticOrRedirect def initialize(options={}) @redirect_base = options[:redirect_base] root = options[:root] || Dir.pwd @file_server = Rack::File.new(root) end def call(env) path = env["PATH_INFO"] resp = @file_server.call(env) if resp.first == 404 [302, { 'Content-Type' => 'text/plain', 'Location' => "#{@redirect_base}#{env['PATH_INFO']}" }, 'Not here!'] else resp end end end Rack::Handler::Thin.run( StaticOrRedirect.new( :redirect_base => 'http://bbc.co.uk' ) )
  31. 31. There's more... • The Rack Gem • Middleware • Rack and Passenger • rackup
  32. 32. rack.rubyforge.org
  33. 33. danwebb.net
  34. 34. Questions?

×