Rack

What is it?

What is it?

...

shelfs?

What is it?

...

frame?

What is it?

...

torture device? oO

a Ruby Webserver Interface

Rack provides a minimal interface between webservers supporting Ruby and Ruby frameworks.

March 3rd, 2007: First public release 0.1.
... 1000+ of commits,
540 forks, 505 closed issues and merged enhancements ...
February 7th, 2013: Thirty fifth public release 1.5.2


just github: rack/rack

How it all works in general?

Usual boring picture

And here comes Rack

If server supports Rack

Thin


Power of EventMachine with multiple concurrent requests

Unicorn


True UNIX way. Follow Github with Cargo Cult.

Phusion Passenger


Runs Python too and much more.

Pow


For OS X only. By 37signals.

WEBrick


Out of box!

Enough talks! Lets code!!!

Introducing config.ru

A file, containing DSL to build Rack environment.
It must contain run or map call to specify the class or classes to run as app.

config.ru is Configuration [of] Rack Up (I think so ;) )

Example

Try to run

How it works?

Stack of middlewares

Variable with request goes trough stack of middleares, unless one of them will return array. (Instead of claiing another).
We will check last middleware. It's our app.

They are pushed during configuration phase

And request goes troug each one

What should we respond?

An Array containing:

  1. HTTP status code
  2. Hash of headers
  3. Array with responce body

Array?! It's Ruby. It's can't be so borring!

There are classes Rack::Request and Rack::Response.
Rack::Request provides a convenient interface to a Rack environment. It is stateless, the environment "env" passed to the constructor will be directly modified.
Rack::Response provides a convenient interface to create a Rack response. It allows setting of headers and cookies, and provides useful defaults (a OK response containing HTML). Your application's "call" should end returning Response#finish.

Let's try it.

Try to create own middleware

In this example we will try to do authentication middleware.

Hmm... Is there any magic?

WE HAVE TO GO DEEPER!

Prepare yourself

Gemfile

Install

config.ru

Start app with "rackup"

Open Rack gem sources

What happened, when we started this command?


1. Invoke of Rack::Server.start bin/rackup#L4

2. Create new instance of Rack::Server and send "start" lib/rack/server.rb#L141

3. Start will do many things. But we are interested in creating app and starting a server. lib/rack/server.rb#L225

4.1. Build app and options from config. Use Rack::Builder to parse "config.ru" lib/rack/server.rb#L277
4.2. Finalize build by chaining middlewares lib/rack/server.rb#L304

5. Find supported server to run application. It uses Rack::Handler lib/rack/server.rb#L268

Where can I find a server?


1. Rack::Handler will try to guess best server to start our app. lib/rack/handler.rb#L46
2. It will try to pick any of Thin, Puma, WEBrick. In our example, we have WEBrick. lib/rack/handler.rb#L34

3. After server is picked, it will receive run lib/rack/handler/webrick.rb#L8
There is a manual on WEBrick: stdlib-1.9.3/libdoc/webrick/rdoc/WEBrick

Wooh! We made it. Now we see in console...


The HTTP request

Let's request a URL by curl... What will it send?

What will happen, after WEBrick receives data trough TCP socket?


At the end, it will call service method.
The handler we used, was inherited from WEBrick::HTTPServlet::AbstractServlet
But "service" method was re-defined in Rack handler lib/rack/handler/webrick.rb#L34

It receives two params of classes WEBrick::HTTPRequest and WEBrick::HTTPResponse passed to the method.
The magic is done by WEBrick::HTTPRequest.meta_vars. This method provides hash with variables defined by the revision 3 of “The WWW Common Gateway Interface Version 1.1”

App is called in 60th line. And we get response, that is written to res parameter.

List of sites, I took knowlage from:

/

#