Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow passing a configuration to Builder, and use it when building
This adds Rack::Builder::Config, which stores information on the server's configuration, such as whether it is multithreaded or supports reentrancy. Middleware can use the configuration by defining a rackup method in addition to a new method. If the rackup method is defined, it is called instead of the new method, with the configuration as the first argument and with the remaining arguments and block the same as what would be passed to new. In cases where the server's configuration indicates the middleware is not needed, the middleware rackup method can be just return the app itself. To handle the very rare case where a middleware would want to delegate to other middleware in certain server configurations, and doesn't know whether the other middleware supports the rackup method or not, The configuration object supports a rackup method, which will call rackup on the middleware if defined, or new otherwise. So if middleware A wants to use external middleware B in a certain server configuration, middleware A's rackup method could be something like: def self.rackup(config, app) if config.multithread? config.rackup(MiddlewareB, app) else new(app) end end The configuration rackup method is also used internally to implement the builder. This readds Rack::Lock, using the rackup method, which only uses the Rack::Lock middleware if the configuration indicates the server is multithreaded. The advantage of this approach is that it doesn't require exposing the entire builder API to the middleware, it only exposes the server configuration, which is all the middleware should need to appropriately configure itself.
- Loading branch information
1 parent
7a446d2
commit b67c697
Showing
4 changed files
with
98 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'logger' | ||
|
||
module Rack | ||
# Sets up rack.logger to write to rack.errors stream | ||
class Lock | ||
def initialize(app) | ||
@app = app | ||
@mutex = ::Thread::Mutex.new | ||
end | ||
|
||
def call(env) | ||
@mutex.synchronize do | ||
@app.call(env) | ||
end | ||
end | ||
|
||
def self.rackup(config, app) | ||
if config.multithread? | ||
new(app) | ||
else | ||
app | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# frozen_string_literal: true | ||
|
||
require_relative 'helper' | ||
|
||
describe Rack::Lock do | ||
it "constructs lock when builder is multithreaded" do | ||
x = Object.new | ||
builder = Rack::Builder.new(config: Rack::Builder::Config.new(multithread: true)) do | ||
use Rack::Lock | ||
run x | ||
end | ||
|
||
builder.to_app.must_be_kind_of Rack::Lock | ||
end | ||
|
||
it "ignores lock when builder is not multithreaded" do | ||
x = Object.new | ||
builder = Rack::Builder.new(config: Rack::Builder::Config.new(multithread: false)) do | ||
use Rack::Lock | ||
run x | ||
end | ||
|
||
builder.to_app.must_be_same_as x | ||
end | ||
end |