class Rack::Builder
You can use map
to construct a Rack::URLMap in a convenient way.use
adds middleware to the stack, run
dispatches to an application.
run app
end
run lambda { |env| [200, {‘content-type’ => ‘text/plain’}, [‘OK’]] }
use Rack::CommonLogger
app = Rack::Builder.app do
Or
run app
end
end
run lambda { |env| [200, {‘content-type’ => ‘text/plain’}, [‘OK’]] }
map “/ok” do
use Rack::CommonLogger
app = Rack::Builder.new do
Example:
by a Rack-compatible web server.
instantiate several middleware and a final application which are hosted
applications. It is primarily used to parse config.ru
files which
Rack::Builder provides a domain-specific language (DSL) to construct Rack
def self.app(default_app = nil, &block)
Create a new Rack::Builder instance and return the Rack application
def self.app(default_app = nil, &block) self.new(default_app, &block).to_app end
def self.load_file(path)
require './app.rb'
use Rack::ContentLength
$ cat config.ru
Example config.ru file:
use of +__END__+ will not result in a syntax error.
Ignores content in the file after +__END__+, so that
contents as if specified inside a Rack::Builder block.
Load the given file as a rackup file, treating the
def self.load_file(path) config = ::File.read(path) config.slice!(/\A#{UTF_8_BOM}/) if config.encoding == Encoding::UTF_8 if config[/^#\\(.*)/] fail "Parsing options from the first comment line is no longer supported: #{path}" end config.sub!(/^__END__\n.*\Z/m, '') return new_from_string(config, path) end
def self.new_from_string(builder_script, file = "(rackup)")
Evaluate the given +builder_script+ string in the context of
def self.new_from_string(builder_script, file = "(rackup)") # We want to build a variant of TOPLEVEL_BINDING with self as a Rack::Builder instance. # We cannot use instance_eval(String) as that would resolve constants differently. binding, builder = TOPLEVEL_BINDING.eval('Rack::Builder.new.instance_eval { [binding, self] }') eval builder_script, binding, file return builder.to_app end
def self.parse_file(path)
# process's current directory. After requiring,
# requires ./my_app.rb, which should be in the
Rack::Builder.parse_file('./my_app.rb')
# contains Rack application
# load path. After requiring, assumes App constant
# requires app.rb, which can be anywhere in Ruby's
Rack::Builder.parse_file('app.rb')
# Rack application built using Rack::Builder.new
Rack::Builder.parse_file('config.ru')
Examples:
to guess which constant will be the Rack application to run.
required and Rack will use the basename of the file
If the config file does not end in +.ru+, it is
specified inside a Rack::Builder block.
rackup file and the contents will be treated as if
If the config file ends in +.ru+, it is treated as a
Parse the given config file to get a Rack application.
def self.parse_file(path) if path.end_with?('.ru') return self.load_file(path) else require path return Object.const_get(::File.basename(path, '.rb').split('_').map(&:capitalize).join('')) end end
def call(env)
this rebuilds the Rack application and runs the warmup code (if any)
Call the Rack application generated by this builder instance. Note that
def call(env) to_app.call(env) end
def freeze_app
Freeze the app (set using run) and all middleware instances when building the application
def freeze_app @freeze_app = true end
def generate_map(default_app, mapping)
Generate a URLMap instance by generating new Rack applications for each
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
def initialize(default_app = nil, &block)
default application if +run+ is not called later. If a block
Initialize a new Rack::Builder instance. +default_app+ specifies the
def initialize(default_app = nil, &block) @use = [] @map = nil @run = default_app @warmup = nil @freeze_app = false instance_eval(&block) if block_given? end
def map(path, &block)
Note that providing a +path+ of +/+ will ignore any default application given in a +run+ statement
This example includes a piece of middleware which will run before +/heartbeat+ requests hit +Heartbeat+.
end
run App.new
end
run Heartbeat.new
use Middleware
map '/heartbeat' do
app = Rack::Builder.app do
The +use+ method can also be used inside the block to specify middleware to run under a specific path:
run app
end
run App.new
end
run Heartbeat.new
map '/heartbeat' do
app = Rack::Builder.app do
end
end
[200, { "content-type" => "text/plain" }, ["OK"]]
def call(env)
class Heartbeat
end
end
[200, {'content-type' => 'text/plain'}, ["Hello World"]]
def call(env)
class App
default application specified by run outside the block.
the Rack application specified by run inside the block. Other requests will be sent to the
Creates a route within the application. Routes under the mapped path will be sent to
def map(path, &block) @map ||= {} @map[path] = block end
def run(app = nil, &block)
run Heartbeat.new
end
end
[200, { "content-type" => "text/plain" }, ["OK"]]
def call(env)
class Heartbeat
You can also provide a class instance:
run lambda { |env| [200, { "content-type" => "text/plain" }, ["OK"]] }
You can also provide a lambda:
end
[200, { "content-type" => "text/plain" }, ["Hello World!"]]
run do |env|
You can use a block:
returns a Rack response.
Takes a block or argument that is an object that responds to #call and
def run(app = nil, &block) raise ArgumentError, "Both app and block given!" if app && block_given? @run = app || block end
def to_app
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
def use(middleware, *args, &block)
The +call+ method in this example sets an additional environment key which then can be
All requests through to this application will first be processed by the middleware class.
run lambda { |env| [200, { "content-type" => "text/plain" }, ["OK"]] }
use Middleware
end
end
@app.call(env)
env["rack.some_header"] = "setting an example"
def call(env)
end
@app = app
def initialize(app)
class Middleware
Specifies middleware to use in a stack.
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
def warmup(prc = nil, &block)
use SomeMiddleware
end
client.get('/')
client = Rack::MockRequest.new(app)
warmup do |app|
before the Rack application is returned by to_app.
Takes a lambda or block that is used to warm-up the application. This block is called
def warmup(prc = nil, &block) @warmup = prc || block end