El método run de Rack::Handler::WEBrick

Véa por ejemplo una versión del código de run de Rack::Handler::WEBrick: (puede encontrarse una en Rack::Handler::WEBrick):

  def self.run(app, options={})
    options[:BindAddress] = options.delete(:Host) if options[:Host]
    options[:Port] ||= 8080
    @server = ::WEBrick::HTTPServer.new(options)
    @server.mount "/", Rack::Handler::WEBrick, app 
    yield @server  if block_given?
    @server.start
  end

  1. Vemos que run espera un objeto app que representa la aplicación y un hash de opciones.
  2. Si arrancamos un servidor en 127.0.0.1, sólo escucha en localhost; si lo arrancamos en 0.0.0.0, escucha a cualquier IP, en particular en nuestra IP local.

    Veamos el siguiente experimento:

    [~/local/src/ruby/sinatra/rack/rack-testing/bindaddress(master)]$ cat bindaddress0000.rb 
    require 'rack'
    
    #ENV['RACK-ENV'] = 'production'
    
    app = lambda { |e| 
     [200, { 'content-type' => 'text/html'}, ["<h1>hello world!</h1>"]]
     }
    
     Rack::Handler::WEBrick.run app, { :Host => '0.0.0.0' }
    

    [~/local/src/ruby/sinatra/rack/rack-testing/bindaddress(master)]$ ifconfig  en0 | grep 'inet\>'
      inet 192.168.0.103
    

    [~/local/src/ruby/sinatra/rack/rack-testing/bindaddress(master)]$ ruby bindaddress0000.rb 
    [2013-09-23 12:04:36] INFO  WEBrick 1.3.1
    [2013-09-23 12:04:36] INFO  ruby 1.9.3 (2013-02-22) [x86_64-darwin11.4.2]
    [2013-09-23 12:04:36] INFO  WEBrick::HTTPServer#start: pid=8720 port=8080
    

    [~/local/src/ruby/sinatra/rack/rack-testing/bindaddress(master)]$ curl -v 'http://192.168.0.103:8080'* About to connect() to 192.168.0.103 port 8080 (#0)
    *   Trying 192.168.0.103... connected
    * Connected to 192.168.0.103 (192.168.0.103) port 8080 (#0)
    > GET / HTTP/1.1
    > User-Agent: curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8y zlib/1.2.5
    > Host: 192.168.0.103:8080
    > Accept: */*
    > 
    < HTTP/1.1 200 OK 
    < Content-Type: text/html
    < Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-02-22)
    < Date: Mon, 23 Sep 2013 11:11:40 GMT
    < Content-Length: 21
    < Connection: Keep-Alive
    < 
    * Connection #0 to host 192.168.0.103 left intact
    * Closing connection #0
    <h1>hello world!</h1>
    

     [~/local/src/ruby/sinatra/rack/rack-testing/bindaddress(master)]$ cat bindaddress127001.rb 
     require 'rack'
    
     #ENV['RACK-ENV'] = 'production'
    
     app = lambda { |e| 
      [200, { 'content-type' => 'text/html'}, ["<h1>hello world!</h1>"]]
      }
    
      Rack::Handler::WEBrick.run app, { :Host => '127.0.0.1' }
    

    [~/local/src/ruby/sinatra/rack/rack-testing/bindaddress(master)]$ ruby bindaddress127001.rb 
    [2013-09-23 12:13:07] INFO  WEBrick 1.3.1
    [2013-09-23 12:13:07] INFO  ruby 1.9.3 (2013-02-22) [x86_64-darwin11.4.2]
    [2013-09-23 12:13:07] INFO  WEBrick::HTTPServer#start: pid=8993 port=8080
    

    [~/local/src/ruby/sinatra/rack/rack-testing/bindaddress(master)]$ curl -v 'http://192.168.0.103:8080'
    * About to connect() to 192.168.0.103 port 8080 (#0)
    *   Trying 192.168.0.103... Connection refused
    * couldn't connect to host
    * Closing connection #0
    curl: (7) couldn't connect to host
    
  3. Luego se crea un nuevo objeto que representa al servidor con @server = ::WEBrick::HTTPServer.new(options).

    Esto crea un nuevo objeto WEBrick HTTP server de acuerdo a options. Un servidor HTTP tiene los siguientes atributos:

    1. AccessLog: An array of access logs. See WEBrick::AccessLog
    2. BindAddress: Local address for the server to bind to
    3. DocumentRoot: Root path to serve files from
    4. DocumentRootOptions: Options for the default HTTPServlet::FileHandler
    5. HTTPVersion: The HTTP version of this server
    6. Port: Port to listen on
    7. RequestCallback: Called with a request and response before each request is serviced.
    8. RequestTimeout: Maximum time to wait between requests
    9. ServerAlias: Array of alternate names for this server for virtual hosting
    10. ServerName: Name for this server for virtual hosting
  4. mount recibe un directorio y un servlet. Un servlet es una clase que se usa para extender las capacidades de un servidor. En este caso estamos extendiendo @server que es un servidor WEBrick::HTTPServer con las capacidades definidas en la clase Rack::Handler::WEBrick. La sintáxis de mount es:
       mount(dir, servlet, *options)
    
    Las opciones son pasadas al servlet en el momento de la creación del servlet.
  5. Observamos que run puede ir seguido de un bloque al que se le pasa como argumento el objeto server
    yield @server  if block_given?
    
    Este bloque puede ser usado como una nueva oportunidad para configurar el server
  6. Se arranca el servidor con la llamada al método start definido en webrick/server.rb

Casiano Rodriguez León 2015-01-07