Quick entry into the rack

Original author: Satish Talim
  • Transfer

What is Rack?

According to Christian Neukirchen, the author of the rack gem, it was created to provide a minimal API for connecting web servers supporting Ruby (WEBrick, Mongrel, etc.) and ruby ​​web frameworks (Rails, Sinatra, etc.).

Frameworks such as Sinatra are built on top of Rack, or they have a rack interface that allows web application servers to connect to them.

The purpose of the rack is simple - it makes it easy to handle HTTP requests.

HTTP is a simple protocol: it basically describes the format of the data that is sent to the server and which is returned to the client. The HTTP request and the HTTP response have a very similar structure. An HTTP request is a triple consisting of a method-resource pair, a set of headers and a request body, while an HTTP HTTP response consists of a response code, a set of headers and an optional response body.

Mapping Rack is close to this. A Rack application is a ruby ​​object that has a call method that takes a single argument, environment, and returns an array of three elements: status, headers and response body.

Rack includes handlers and adapters. The former connect it to ruby ​​web servers, the latter connect to frameworks.

Using middleware, you can change the rack to the needs of your application. The main idea of ​​rack middleware is to process the request before it gets into the application, and process the response before returning it to the client.



Install Rack

Please note that everything that is mentioned in this article is tested on ruby ​​1.9.2 installed on Windows ( host - master - approx. Per. ).

Check if you have a rack installed. To do this, open the console: If require returned true, it means that rack is installed. Otherwise, you will receive an error message of the type: This is fixed simply by the gem install rack command.

# irb --simple-prompt
>> require 'rack'
=> true

LoadError: no such file to load -- rack

Quick tour of the proc object

Remember the proc object? In ruby, blocks are not objects, but they can be converted to objects of the Proc class. This can be done by calling the lambda method of the Object class. A block created using lambda behaves like a ruby ​​method. And the Proc class has a call method that calls the block for execution.

>> my_rack_proc = lambda {puts 'Rack Intro'}
=> #
>> # method call invokes the block
?> my_rack_proc.call
Rack Intro
=> nil

The simplest rack application - my_rack_proc

As already mentioned, our rack application is an object (not a class) that responds to the call method and takes one argument - the environment ( it is also environment - approx. Trans. ). The environment must be an instance of the Hash class. An application should return an array of three values: a status code (greater than or equal to 100), headers (also a hash), and bodies (the body is usually an array of strings, an application instance, or a file. The response body should respond to the each method and output only string values). Let's create our new proc object. Now you can call my_rack_proc: my_rack_proc is our one-line Rack. In the above example, we used an empty hash for the headers. Instead, let's have something in the header as follows:

>> my_rack_proc = lambda { |env| [200, {}, ["Hello. The time is #{Time.now}"]] }
=> #

>> my_rack_proc.call({})
=> [200, {}, ["Hello. The time is 2011-10-24 09:18:56 +0530"]]

>> my_rack_proc = lambda { |env| [200, {"Content-Type" => "text/plain"}, ["Hello. The time is #{Time.now}"]] }
=> #
>> my_rack_proc.call({})
=> [200, {"Content-Type" => "text/plain"}, ["Hello. The time is 2011-10-24 09:18:56 +0530"]]

We can run our rack application using any of the handlers.

Let's see what types of handlers are available to us: To use WEBrick (by default WEBrick is a server installed with Ruby), enter: All these handlers have a run method that launches a rack application: Open the localhost page in the browser and you should see a line like:

>> Rack::Handler.constants
=> [:CGI, :FastCGI, :Mongrel, :EventedMongrel, :SwiftipliedMongrel, :WEBrick, :LSWS, :SCGI, :Thin]

>> Rack::Handler::WEBrick
=> Rack::Handler::WEBrick

>> Rack::Handler::WEBrick.run my_rack_proc
[2011-10-24 10:00:45] INFO WEBrick 1.3.1
[2011-10-24 10:00:45] INFO ruby 1.9.2 (2011-07-09) [i386-mingw32]
[2011-10-24 10:00:45] INFO WEBrick::HTTPServer#start: pid=1788 port=80

Hello The time is 2011-10-24 10:02:20 +0530

Note: If you already have something running on port 80, you can run the application on another port.
>> Rack::Handler::WEBrick.run my_rack_proc, :Port => 9876
[2011-10-24 11:32:21] INFO WEBrick 1.3.1
[2011-10-24 11:32:21] INFO ruby 1.9.2 (2011-07-09) [i386-mingw32]
[2011-10-24 11:32:21] INFO WEBrick::HTTPServer # start: pid = 480 port = 9876

Another rack application is my_method

Rack-application is not necessarily lambda. It can also be a method. At localhost you will again see:

>> def my_method env
>> [200, {}, ["method called"]]
>> end
=> nil
>> Rack::Handler::WEBrick.run method(:my_method)
[2011-10-24 14:32:05] INFO WEBrick 1.3.1
[2011-10-24 14:32:05] INFO ruby 1.9.2 (2011-07-09) [i386-mingw32]
[2011-10-24 14:32:05] INFO WEBrick::HTTPServer#start: pid=1644 port=80

method called

Method objects are created using the Object # method . They are associated with a specific object (and not just with a class). They can be used to call a method within an object. Method.call is a method that calls a method ( Oh, hack, hack ... - approx. Per. ) With the specified arguments and returns the value that the called method returns.

Using rackup

Gem rack comes with a bunch of useful pieces that simplify the life of the developer. One of these pieces is rackup.

Rackup is a useful tool for launching rack applications. Rackup itself determines the environment in which it is running and runs your application as FastCGI, CGI, or stand-alone with Mongrel or WEBrick - all with the same de configuration.

To use rackup, you must create its configuration file. By convention, you must use the .ru extension for this config. By default, rackup starts on port 9292.

Let's create a config.ru file containing:

run lambda { |env| [200, {"Content-Type" => "text/plain"}, ["Hello. The time is #{Time.now}"]] }

This file contains the word run , which can be called by everything that responds to the .call method.

To start the rack-application in the folder with the config.ru file, enter: Now, at the localhost address : 9292 / we will again be given the following page: Let's move our application from the config.ru file to my_app.rb:

$ rackup config.ru
[2011-10-24 15:18:03] INFO WEBrick 1.3.1
[2011-10-24 15:18:03] INFO ruby 1.9.2 (2011-07-09) [i386-mingw32]
[2011-10-24 15:18:03] INFO WEBrick::HTTPServer # start: pid = 3304 port = 9292

Hello. The time is 2011-10-24 15:18:10 +0530

# my_app.rb
class MyApp
  def call(env)
    [200, {"Content-Type" => "text/html"}, ["Hello Rack Participants"]]

Also change config.ru:

require './my_app'
run MyApp.new

Now you can again start the application (using the "rackup config.ru") and check whether the page is returned to the browser.

We deploy the rack application on Heroku.

(This piece of the article was ruthlessly cut by me, because it describes the installation of git on windows and the deployment on heroku, which has nothing to do with the article itself. If you are interested, you can read it in the original - approx. Per. )

Using rack middleware

It was previously mentioned that between the server and the framework, the rack can be configured for your needs using middleware.

Rackup also uses a method that accepts middleware. Let's use one of the built-in rack middleware.

You must have noticed that every time after changing the config.ru or my_app.rb files, you need to restart the WEBrick server. This can be avoided using middleware Rack :: Reloader. Edit config.ru:

require './my_app'
use Rack::Reloader
run MyApp.new

And my_app.rb:

# my_app.rb
class MyApp
  def call(env)
    [200, {"Content-Type" => "text/html"}, ["Hello Rack Participants from across the globe"]]

Launch the application and open the page with it in the browser. Now change the text from “Hello Rack Participants from across the globe!” To “Hello Rack Participants from across the world!”. After updating the page in the browser, you will see the edited text without restarting the web server.

Writing Your Own Middleware

Middleware always in practice serves to wrap your internal application.

Let's create a simple middleware that adds text to the body of the http response. To do this, create the MyRackMiddleware class:

class MyRackMiddleware
  def initialize(appl)
    @appl = appl
  def call(env)

In the code above, to get the original response body, we initialize the MyRackMiddleware class, passing it the appl (appl).

Now change the .call method:

def call(env)
  status, headers, body = @appl.call(env) # we now call the inner application

In the above code, we have access to the original response body, which we can now change. Rack does not guarantee you that the body will be a string. It can also be an object, but we know that when you call the .each method, everything returned will be a string. We use this in the .call method:

def call(env)
  status, headers, body = @appl.call(env)
  append_s = "... greetings from RubyLearning!!"
  [status, headers, body << append_s]

Now change the config.ru file:

require './my_app'
require './myrackmiddleware'
use Rack::Reloader
use MyRackMiddleware
run MyApp.new

We launch the application and in the browser you can see "Hello Rack Participants from across the globe ... greetings from RubyLearning !!"

Rack and Sinatra

Lastly, here is a simple example of using rack with the sinatra framework.

Let's create a trivial application my_sinatra.rb that will use rack middleware:

require 'sinatra'
require './rackmiddleware'
use RackMiddleware
get '/' do
  'Welcome to all'

Now let's put in a simple middleware class that will record time to the console to process the request from the application. Create the rackmiddleware.rb file:

class RackMiddleware
  def initialize(appl)
    @appl = appl
  def call(env)
    start = Time.now
    status, headers, body = @appl.call(env) # call our Sinatra app
    stop = Time.now
    puts "Response Time: #{stop-start}" # display on console
    [status, headers, body]

Now change the config.ru file:

require "./my_sinatra"
run Sinatra::Application

( Next, there is a block of text again on how to deploy to Heroka, use git, etc. I don’t think it will be interesting for you - approx. per. )

Now, after launching the application, a line with approximately the following will be written to the console for each request contents:

?[36m2011-10-26T05:40:06+00:00 app[web.1]:?[0m *** Response Time ***: 0.000297385

That's all. I hope you enjoyed this entry into the rack. Happy racking!

Also popular now: