Class: Rack::Builder
- Inherits:
-
Object
- Object
- Rack::Builder
- Defined in:
- lib/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, {'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.
Constant Summary collapse
- UTF_8_BOM =
'\xef\xbb\xbf'
Class Method Summary collapse
- .app(default_app = nil, &block) ⇒ Object
- .load_file(path, opts = Server::Options.new) ⇒ Object
- .new_from_string(builder_script, file = "(rackup)") ⇒ Object
- .parse_file(config, opts = Server::Options.new) ⇒ Object
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#freeze_app ⇒ Object
Freeze the app (set using run) and all middleware instances when building the application in to_app.
-
#initialize(default_app = nil, &block) ⇒ Builder
constructor
A new instance of Builder.
-
#map(path, &block) ⇒ Object
Creates a route within the application.
-
#run(app) ⇒ Object
Takes an argument that is an object that responds to #call and returns a Rack response.
- #to_app ⇒ Object
-
#use(middleware, *args, &block) ⇒ Object
Specifies middleware to use in a stack.
-
#warmup(prc = nil, &block) ⇒ Object
Takes a lambda or block that is used to warm-up the application.
Constructor Details
#initialize(default_app = nil, &block) ⇒ Builder
Returns a new instance of Builder.
69 70 71 72 |
# 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 |
Class Method Details
.app(default_app = nil, &block) ⇒ Object
74 75 76 |
# File 'lib/rack/builder.rb', line 74 def self.app(default_app = nil, &block) self.new(default_app, &block).to_app end |
.load_file(path, opts = Server::Options.new) ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/rack/builder.rb', line 48 def self.load_file(path, opts = Server::Options.new) = {} cfgfile = ::File.read(path) cfgfile.slice!(/\A#{UTF_8_BOM}/) if cfgfile.encoding == Encoding::UTF_8 if cfgfile[/^#\\(.*)/] && opts = opts.parse! $1.split(/\s+/) end cfgfile.sub!(/^__END__\n.*\Z/m, '') app = new_from_string cfgfile, path return app, end |
.new_from_string(builder_script, file = "(rackup)") ⇒ Object
64 65 66 67 |
# 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 |
.parse_file(config, opts = Server::Options.new) ⇒ Object
38 39 40 41 42 43 44 45 46 |
# 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 |
Instance Method Details
#call(env) ⇒ Object
176 177 178 |
# File 'lib/rack/builder.rb', line 176 def call(env) to_app.call(env) end |
#freeze_app ⇒ Object
Freeze the app (set using run) and all middleware instances when building the application in to_app.
163 164 165 |
# File 'lib/rack/builder.rb', line 163 def freeze_app @freeze_app = true end |
#map(path, &block) ⇒ Object
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
.
156 157 158 159 |
# File 'lib/rack/builder.rb', line 156 def map(path, &block) @map ||= {} @map[path] = block end |
#run(app) ⇒ Object
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
120 121 122 |
# File 'lib/rack/builder.rb', line 120 def run(app) @run = app end |
#to_app ⇒ Object
167 168 169 170 171 172 173 174 |
# File 'lib/rack/builder.rb', line 167 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 |
#use(middleware, *args, &block) ⇒ Object
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.
97 98 99 100 101 102 103 |
# 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 |
#warmup(prc = nil, &block) ⇒ Object
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
133 134 135 |
# File 'lib/rack/builder.rb', line 133 def warmup(prc = nil, &block) @warmup = prc || block end |