lib/roda/plugins/middleware.rb in roda-2.23.0 vs lib/roda/plugins/middleware.rb in roda-2.24.0
- old
+ new
@@ -33,26 +33,64 @@
#
# run App
#
# It is possible to use the Roda app as a regular app even when using
# the middleware plugin.
+ #
+ # You can support configurable middleware by passing a block when loading
+ # the plugin:
+ #
+ # class Mid < Roda
+ # plugin :middleware do |middleware, *args, &block|
+ # middleware.opts[:middleware_args] = args
+ # block.call(middleware)
+ # end
+ #
+ # route do |r|
+ # r.is "mid" do
+ # opts[:middleware_args].join(' ')
+ # end
+ # end
+ # end
+ #
+ # class App < Roda
+ # use Mid, :foo, :bar do |middleware|
+ # middleware.opts[:middleware_args] << :baz
+ # end
+ # end
+ #
+ # # Request to App for /mid returns
+ # # "foo bar baz"
+ #
+ # Note that when supporting configurable middleware via a block, the middleware
+ # used is a subclass of the class loading the plugin, instead of the class itself.
+ # This is done so the same class can be used as middleware with multiple separate
+ # configurations.
module Middleware
# Configure the middleware plugin. Options:
# :env_var :: Set the environment variable to use to indicate to the roda
# application that the current request is a middleware request.
# You should only need to override this if you are using multiple
# roda middleware in the same application.
- def self.configure(app, opts={})
+ def self.configure(app, opts={}, &block)
app.opts[:middleware_env_var] = opts[:env_var] if opts.has_key?(:env_var)
app.opts[:middleware_env_var] ||= 'roda.forward_next'
+ app.opts[:middleware_configure] = block if block
end
# Forward instances are what is actually used as middleware.
class Forwarder
# Store the current middleware and the next middleware to call.
- def initialize(mid, app)
- @mid = mid
+ def initialize(mid, app, *args, &block)
+ @mid = if configure = mid.opts[:middleware_configure]
+ mid = Class.new(mid)
+ configure.call(mid, *args, &block)
+ mid
+ else
+ raise RodaError, "cannot provide middleware args or block unless loading middleware plugin with a block" if block || !args.empty?
+ mid
+ end
@app = app
end
# When calling the middleware, first call the current middleware.
# If this returns a result, return that result directly. Otherwise,
@@ -74,14 +112,14 @@
end
end
module ClassMethods
# Create a Forwarder instead of a new instance if a non-Hash is given.
- def new(app)
+ def new(app, *args, &block)
if app.is_a?(Hash)
super
else
- Forwarder.new(self, app)
+ Forwarder.new(self, app, *args, &block)
end
end
# Override the route block so that if no route matches, we throw so
# that the next middleware is called.