Class: Rack::Builder

Inherits:
Object
  • Object
show all
Defined in:
rack/rack/builder.rb

Overview

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, => '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.

Class Method Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Builder) initialize(default_app = nil, &block)

Returns a new instance of Builder



53
54
55
56
# File 'rack/rack/builder.rb', line 53

def initialize(default_app = nil,&block)
  @use, @map, @run = [], nil, default_app
  instance_eval(&block) if block_given?
end

Class Method Details

+ (void) app(default_app = nil, &block)



58
59
60
# File 'rack/rack/builder.rb', line 58

def self.app(default_app = nil, &block)
  self.new(default_app, &block).to_app
end

+ (void) new_from_string(builder_script, file = "(rackup)")



48
49
50
51
# File 'rack/rack/builder.rb', line 48

def self.new_from_string(builder_script, file="(rackup)")
  eval "Rack::Builder.new {\n" + builder_script + "\n}.to_app",
    TOPLEVEL_BINDING, file, 0
end

+ (void) parse_file(config, opts = Server::Options.new)



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'rack/rack/builder.rb', line 32

def self.parse_file(config, opts = Server::Options.new)
  options = {}
  if config =~ /\.ru$/
    cfgfile = ::File.read(config)
    if cfgfile[/^#\\(.*)/] && opts
      options = opts.parse! $1.split(/\s+/)
    end
    cfgfile.sub!(/^__END__\n.*\Z/m, '')
    app = new_from_string cfgfile, config
  else
    require config
    app = Object.const_get(::File.basename(config, '.rb').capitalize)
  end
  return app, options
end

Instance Method Details

- (void) call(env)



137
138
139
# File 'rack/rack/builder.rb', line 137

def call(env)
  to_app.call(env)
end

- (void) map(path, &block)

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.



126
127
128
129
# File 'rack/rack/builder.rb', line 126

def map(path, &block)
  @map ||= {}
  @map[path] = block
end

- (void) run(app)

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



103
104
105
# File 'rack/rack/builder.rb', line 103

def run(app)
  @run = app
end

- (void) to_app



131
132
133
134
135
# File 'rack/rack/builder.rb', line 131

def to_app
  app = @map ? generate_map(@run, @map) : @run
  fail "missing run or map statement" unless app
  @use.reverse.inject(app) { |a,e| e[a] }
end

- (void) use(middleware, *args, &block)

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.



81
82
83
84
85
86
87
# File 'rack/rack/builder.rb', line 81

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