class Rack::Builder
Rack::Builder
implements a small DSL to iteratively construct Rack
applications.
Example:
require 'rack/lobster' app = Rack::Builder.new do use Rack::CommonLogger use Rack::ShowExceptions map "/lobster" do use Rack::Lint run Rack::Lobster.new end end run app
Or
app = Rack::Builder.app do use Rack::CommonLogger run lambda { |env| [200, {'Content-Type' => 'text/plain'}, ['OK']] } end run app
use
adds middleware to the stack, run
dispatches to an application. You can use map
to construct a Rack::URLMap
in a convenient way.
Constants
Public Class Methods
# File lib/rack/builder.rb, line 74 def self.app(default_app = nil, &block) self.new(default_app, &block).to_app end
# File lib/rack/builder.rb, line 48 def self.load_file(path, opts = Server::Options.new) options = {} cfgfile = ::File.read(path) cfgfile.slice!(/\A#{UTF_8_BOM}/) if cfgfile.encoding == Encoding::UTF_8 if cfgfile[/^#\\(.*)/] && opts options = opts.parse! $1.split(/\s+/) end cfgfile.sub!(/^__END__\n.*\Z/m, '') app = new_from_string cfgfile, path return app, options end
# File lib/rack/builder.rb, line 69 def initialize(default_app = nil, &block) @use, @map, @run, @warmup, @freeze_app = [], nil, default_app, nil, false instance_eval(&block) if block_given? end
# File lib/rack/builder.rb, line 64 def self.new_from_string(builder_script, file = "(rackup)") eval "Rack::Builder.new {\n" + builder_script + "\n}.to_app", TOPLEVEL_BINDING, file, 0 end
# File lib/rack/builder.rb, line 38 def self.parse_file(config, opts = Server::Options.new) if config.end_with?('.ru') return self.load_file(config, opts) else require config app = Object.const_get(::File.basename(config, '.rb').split('_').map(&:capitalize).join('')) return app, {} end end
Public Instance Methods
# File lib/rack/builder.rb, line 175 def call(env) to_app.call(env) end
Freeze the app (set using run) and all middleware instances when building the application in to_app.
# File lib/rack/builder.rb, line 162 def freeze_app @freeze_app = true end
Creates a route within the application.
Rack::Builder.app do map '/' do run Heartbeat end end
The use
method can also be used here to specify middleware to run under a specific path:
Rack::Builder.app do map '/' do use Middleware run Heartbeat end end
This example includes a piece of middleware which will run before requests hit Heartbeat
.
# File lib/rack/builder.rb, line 155 def map(path, &block) @map ||= {} @map[path] = block end
Takes an argument that is an object that responds to call
and returns a Rack
response. The simplest form of this is a lambda object:
run lambda { |env| [200, { "Content-Type" => "text/plain" }, ["OK"]] }
However this could also be a class:
class Heartbeat def self.call(env) [200, { "Content-Type" => "text/plain" }, ["OK"]] end end run Heartbeat
# File lib/rack/builder.rb, line 119 def run(app) @run = app end
# File lib/rack/builder.rb, line 166 def to_app app = @map ? generate_map(@run, @map) : @run fail "missing run or map statement" unless app app.freeze if @freeze_app app = @use.reverse.inject(app) { |a, e| e[a].tap { |x| x.freeze if @freeze_app } } @warmup.call(app) if @warmup app end
Specifies middleware to use in a stack.
class Middleware def initialize(app) @app = app end def call(env) env["rack.some_header"] = "setting an example" @app.call(env) end end use Middleware run lambda { |env| [200, { "Content-Type" => "text/plain" }, ["OK"]] }
All requests through to this application will first be processed by the middleware class. The call
method in this example sets an additional environment key which then can be referenced in the application if required.
# File lib/rack/builder.rb, line 97 def use(middleware, *args, &block) if @map mapping, @map = @map, nil @use << proc { |app| generate_map(app, mapping) } end @use << proc { |app| middleware.new(app, *args, &block) } end
Takes a lambda or block that is used to warm-up the application.
warmup do |app| client = Rack::MockRequest.new(app) client.get('/') end use SomeMiddleware run MyApp
# File lib/rack/builder.rb, line 132 def warmup(prc = nil, &block) @warmup = prc || block end
Private Instance Methods
# File lib/rack/builder.rb, line 181 def generate_map(default_app, mapping) mapped = default_app ? { '/' => default_app } : {} mapping.each { |r, b| mapped[r] = self.class.new(default_app, &b).to_app } URLMap.new(mapped) end