Get ordered list of middleware in a generic rack application?

Viewed 17927

The functionality I am looking for is similar to the rake middleware command in Rails, except for a generic rack application.

5 Answers

If you're using a Sinatra app that extends Sinatra::Base, I had to use a slightly modified version of Michael Hale's answer:

require 'rack'
​
def middleware_classes(app)
  r = [app]
  ​
  while ((next_app = r.last.instance_variable_get(:@app)) != nil)
    r << next_app
  end
  ​
  r.map{|e| e.instance_variable_defined?(:@app) ? e.class : e }
end
​
sinatra_app = Rack::Builder.parse_file('config.ru').first
sinatra_rack_builder = sinatra_app.build(sinatra_app)
sinatra_extended_app = sinatra_rack_builder.to_app
rack_app = sinatra_extended_app.app

pp middleware_classes(rack_app)

​ After putting this into a file such as dump_middleware.rb I was able to see the middleware as expected:

$ bundle exec ruby ./dump_middleware.rb
[Rack::Head,
 Rack::NullLogger,
 Rack::Session::Cookie,
 Rack::Protection::FrameOptions,
 Rack::Protection::HttpOrigin,
 Rack::Protection::IPSpoofing,
 Rack::Protection::JsonCsrf,
 Rack::Protection::PathTraversal,
 Rack::Protection::RemoteToken,
 Rack::Protection::SessionHijacking,
 Rack::Protection::XSSHeader,
 Warden::Manager,
 SinatraApp]

There might be a cleaner way to do this.

Try the rack-graph gem by Konstantin Haase.

For some reason, Konstantin has not seen fit to publish this gem on rubygems, so you will either need to add it to your Gemfile using git or install and reference it locally.

# Gemfile
gem 'rack-graph', github: 'rkh/rack-graph'

$ bundle exec rackup -s Graph
# Locally (without bundler/Gemfile):
$ git clone https://github.com/rkh/rack-graph.git
$ ruby -I/path/to/rack-graph/lib $(which rackup) -s Graph

Given the following example Rack application:

# config.ru
Foo = proc { [200, {}, ['Foo']] }
App = proc { [200, {}, ['Ok']] }

map '/foo' do
  use Rack::Runtime
  use Rack::MethodOverride
  run Foo
end

run App

This is the output:

# Output:
Rack::ContentLength
 |- Rack::CommonLogger(stderr)
    |- Rack::ShowExceptions
       |- Rack::Lint
          |- Rack::TempfileReaper
             |- Rack::URLMap
                |- "/foo"
                |  |- Rack::Runtime
                |     |- Rack::MethodOverride
                |        |- Proc(0x00007fd93a97c2d0 /Users/steve/ruby/config.ru:1)
                |
                |- ""
                   |- Proc(0x00007fd93a97c2a8 /Users/steve/ruby/config.ru:2)
Related