William Notowidagdo Kiranatama Staff
Knowledge


We are going to demonstrate a simple Rack Middleware use in Rails. What is Rack Taken directly from its website,
Rack provides a minimal, modular and adaptable interface for developing web applications in Ruby.
By wrapping HTTP requests and response, Rack standardized the interface for a web server to interact with a web application. Rack Middleware Rails has been using Rack since version 2.3 and that gives Rails developers more power at their hands, such as enable Rack Middleware. You might have heard about Rails Metal, which is similar to Middleware because it uses Rack interface to handle a request. The main difference is that Rails Metal acts as the endpoint of a request and returns a response while Middleware acts like a filter that can be used to intercept a request and alter the response. Creating the Middleware To demonstrate Rack Middleware we are going to intercept any request for HTML pages so that we can first tidy up them. We are going to use tidy, Ruby interface to HTML Tidy Library Project. You will need to install HTML Tidy for your distribution first before having the tidy gem installed. We are using tidy-1.0-126.1 on OpenSUSE 11.2 while writing this post. The Middleware we are going to create is just a Ruby class. Create a file named tidy_response.rb inside the lib folder.
require 'tidy'
class TidyResponse
  def initialize(app)
    @app = app
  end

  def call(env)
    status, headers, response = @app.call(env)

    Tidy.path = '/usr/lib/libtidy-0.99.so.0'
    if headers["Content-Type"].include? "text/html"
      xml = Tidy.open do |tidy|
        tidy.options.output_xml = true
        xml = tidy.clean(response.body)
      end
    end

    [status, headers, xml]
  end
end
Please note that you will need to replace the Tidy.path value according to your distribution. Every Middleware classes have an initialize method that takes an application as an argument. As you notice we have created an instance variable called @app that will be a reference to Rails application.
def initialize(app)
  @app = app
end
All Rack applications have a call method that takes an environment hash variable as an argument and returns an array containing an HTTP status, a hash of headers and a response object
status, headers, response = @app.call(env)
In our example here, we first tidy up the response before return it to the client. Configuring the Middleware We have to add a line in the Rails::Initializer.run block so the application knows to treat our new class as Middleware
Rails::Initializer.run do |config|
  config.middleware.use "TidyResponse"
...
To test that our class is being use as a Middleware class we call rake middleware. Our TidyResponse should be list in the output
william@castafiore:/srv/www/htdocs/sandbox/testbed/rails> rake middleware
(in /srv/www/htdocs/sandbox/testbed/rails)
use Rack::Lock
use ActionController::Failsafe
use ActionController::Session::CookieStore, #
use ActionController::ParamsParser
use Rack::MethodOverride
use Rack::Head
use ActionController::StringCoercion
use TidyResponse
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
run ActionController::Dispatcher.new
Testing the Middleware To see whether the HTML is tidy up, we use untidy HTML in our view so when you start the server without using the Middleware, this is what we get when viewing the source of the page Now start the server the view the source of the page using your browser and you should see The result is a much tidier HTML tags and smaller page size, also notice how HTML Tidy correcting the mismatched end tags become Now you have written a working Middleware class. So enjoy your trip with Rack Middleware and feel free to comment your thoughts and questions!