Class: Rack::Builder
Relationships & Source Files | |
Inherits: | Object |
Defined in: | lib/rack/builder.rb |
Overview
Builder
provides a domain-specific language (DSL) to construct ::Rack
applications. It is primarily used to parse config.ru
files which instantiate several middleware and a final application which are hosted by a Rack-compatible web server.
Example:
app = Rack::Builder.new do
use Rack::CommonLogger
map "/ok" do
run lambda { |env| [200, {'content-type' => 'text/plain'}, ['OK']] }
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 URLMap
in a convenient way.
Constant Summary
-
UTF_8_BOM =
# File 'lib/rack/builder.rb', line 39
'\xef\xbb\xbf'
Class Method Summary
-
.app(default_app = nil, &block)
Create a new
Builder
instance and return the::Rack
application generated from it. -
.load_file(path, **options)
Load the given file as a rackup file, treating the contents as if specified inside a
Builder
block. -
.new(default_app = nil, **options, &block) ⇒ Builder
constructor
Initialize a new
Builder
instance. -
.new_from_string(builder_script, path = "(rackup)", **options)
Evaluate the given
builder_script
string in the context of aBuilder
block, returning a::Rack
application. -
.parse_file(path, **options)
Parse the given config file to get a
::Rack
application.
Instance Attribute Summary
-
#options
readonly
Any options provided to the
Builder
instance at initialization.
Instance Method Summary
-
#call(env)
Call the
::Rack
application generated by this builder instance. -
#freeze_app
Freeze the app (set using run) and all middleware instances when building the application in to_app.
-
#map(path, &block)
Creates a route within the application.
- #run(app = nil, &block)
-
#to_app
Return the
::Rack
application generated by this instance. -
#use(middleware, *args, &block)
Specifies middleware to use in a stack.
-
#warmup(prc = nil, &block)
Takes a lambda or block that is used to warm-up the application.
- #generate_map(default_app, mapping) private
Constructor Details
.new(default_app = nil, **options, &block) ⇒ Builder
Initialize a new Builder
instance. default_app
specifies the default application if #run is not called later. If a block is given, it is evaluated in the context of the instance.
# File 'lib/rack/builder.rb', line 116
def initialize(default_app = nil, **, &block) @use = [] @map = nil @run = default_app @warmup = nil @freeze_app = false @options = instance_eval(&block) if block_given? end
Class Method Details
.app(default_app = nil, &block)
Create a new Builder
instance and return the ::Rack
application generated from it.
.load_file(path, **options)
Load the given file as a rackup file, treating the contents as if specified inside a Builder
block.
Ignores content in the file after __END__
, so that use of __END__
will not result in a syntax error.
Example config.ru file:
$ cat config.ru
use Rack::ContentLength
require './app.rb'
run App
# File 'lib/rack/builder.rb', line 87
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
.new_from_string(builder_script, path = "(rackup)", **options)
Evaluate the given builder_script
string in the context of a Builder
block, returning a ::Rack
application.
# File 'lib/rack/builder.rb', line 102
def self.new_from_string(builder_script, path = "(rackup)", ** ) builder = self.new(** ) # 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.call(builder) eval(builder_script, binding, path) return builder.to_app end
.parse_file(path, **options)
Parse the given config file to get a ::Rack
application.
If the config file ends in .ru
, it is treated as a rackup file and the contents will be treated as if specified inside a Builder
block.
If the config file does not end in .ru
, it is required and ::Rack
will use the basename of the file to guess which constant will be the ::Rack
application to run.
Examples:
Rack::Builder.parse_file('config.ru')
# Rack application built using Rack::Builder.new
Rack::Builder.parse_file('app.rb')
# requires app.rb, which can be anywhere in Ruby's
# load path. After requiring, assumes App constant
# is a Rack application
Rack::Builder.parse_file('./my_app.rb')
# requires ./my_app.rb, which should be in the
# process's current directory. After requiring,
# assumes MyApp constant is a Rack application
Instance Attribute Details
#options (readonly)
Any options provided to the Builder
instance at initialization. These options can be server-specific. Some general options are:
-
:isolation
: One ofprocess
,thread
orfiber
. The execution isolation model to use.
# File 'lib/rack/builder.rb', line 132
attr :
Instance Method Details
#call(env)
# File 'lib/rack/builder.rb', line 276
def call(env) to_app.call(env) end
#freeze_app
Freeze the app (set using run) and all middleware instances when building the application in to_app.
# File 'lib/rack/builder.rb', line 259
def freeze_app @freeze_app = true end
#generate_map(default_app, mapping) (private)
#map(path, &block)
Creates a route within the application. Routes under the mapped path will be sent to the ::Rack
application specified by run inside the block. Other requests will be sent to the default application specified by run outside the block.
class App
def call(env)
[200, {'content-type' => 'text/plain'}, ["Hello World"]]
end
end
class Heartbeat
def call(env)
[200, { "content-type" => "text/plain" }, ["OK"]]
end
end
app = Rack::Builder.app do
map '/heartbeat' do
run Heartbeat.new
end
run App.new
end
run app
The #use method can also be used inside the block to specify middleware to run under a specific path:
app = Rack::Builder.app do
map '/heartbeat' do
use Middleware
run Heartbeat.new
end
run App.new
end
This example includes a piece of middleware which will run before /heartbeat
requests hit Heartbeat
.
Note that providing a path
of /
will ignore any default application given in a #run statement outside the block.
# File 'lib/rack/builder.rb', line 252
def map(path, &block) @map ||= {} @map[path] = block end
#run(app = nil, &block)
Takes a block or argument that is an object that responds to #call and returns a ::Rack
response.
You can use a block:
run do |env|
[200, { "content-type" => "text/plain" }, ["Hello World!"]]
end
You can also provide a lambda:
run lambda { |env| [200, { "content-type" => "text/plain" }, ["OK"]] }
You can also provide a class instance:
class Heartbeat
def call(env)
[200, { "content-type" => "text/plain" }, ["OK"]]
end
end
run Heartbeat.new
#to_app
Return the ::Rack
application generated by this instance.
#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.
#warmup(prc = nil, &block)
# File 'lib/rack/builder.rb', line 209
def warmup(prc = nil, &block) @warmup = prc || block end