class Middleware::Runner
This is a basic runner for middleware stacks. This runner does the default expected behavior of running the middleware stacks in order, then reversing the order.
Constants
- EMPTY_MIDDLEWARE
A middleware which does nothing
Public Class Methods
new(stack)
click to toggle source
Build a new middleware runner with the given middleware stack.
Note: This class usually doesn't need to be used directly. Instead, take a look at using the {Builder} class, which is a much friendlier way to build up a middleware stack.
@param [Array] stack An array of the middleware to run.
# File lib/middleware/runner.rb, line 17 def initialize(stack) # We need to take the stack of middleware and initialize them # all so they call the proper next middleware. @kickoff = build_call_chain(stack) end
Public Instance Methods
call(env)
click to toggle source
Run the middleware stack with the given state bag.
@param [Object] env The state to pass into as the initial
environment data. This is usual a hash of some sort.
# File lib/middleware/runner.rb, line 27 def call(env) # We just call the kickoff middleware, which is responsible # for properly calling the next middleware, and so on and so # forth. @kickoff.call(env) end
Protected Instance Methods
build_call_chain(stack)
click to toggle source
This takes a stack of middlewares and initializes them in a way that each middleware properly calls the next middleware.
# File lib/middleware/runner.rb, line 38 def build_call_chain(stack) # We need to instantiate the middleware stack in reverse # order so that each middleware can have a reference to # the next middleware it has to call. The final middleware # is always the empty middleware, which does nothing but return. stack.reverse.inject(EMPTY_MIDDLEWARE) do |next_middleware, current_middleware| # Unpack the actual item klass, args, block = current_middleware # Default the arguments to an empty array. Otherwise in Ruby 1.8 # a `nil` args will actually pass `nil` into the class. Not what # we want! args ||= [] if klass.is_a?(Class) # If the klass actually is a class, then instantiate it with # the app and any other arguments given. klass.new(next_middleware, *args, &block) elsif klass.respond_to?(:call) # Make it a lambda which calls the item then forwards up # the chain. lambda do |env| next_middleware.call(klass.call(env, *args)) end else fail "Invalid middleware, doesn't respond to `call`: #{klass.inspect}" end end end