Evil client supports stack of rack-compatible middleware which is specific for every scope and operation.

As usual, every middleware is just an object wrapped around some application. It should:

  • initialize with the only parameter app for the rest of stack, wrapped around connection,
  • define the only instance method #call which takes a rack environment, and returns a rack response.

The example of valid middleware which adds the tag "FOO" to the request header:

class Foo
  def call(env)
    env["HTTP_Variables"]["Tag"] = "FOO"
    @app.call env
  end

  private

  def initialize(app)
    @app = app
  end
end

Use the middleware helper method to add a specific class to a stack. You can do this at any level of nesting:

class CatsAPI < Evil::Client
  # ...
  middleware Foo

  scope :cats do
    option :version, proc(&:to_i)
    # ...
    middleware { version < 2 ? Bar : [Bar, Baz] }

    operation :fetch do
      middleware { Qux }
      # ...
    end
  end
end

# Depending on version, this will send rack request to either
# [Foo, Bar, Qux, Evil::Client::Connection]      (versions 1-)
# [Foo, Bar, Baz, Qux, Evil::Client::Connection] (versions 2+)
#
# The response will be processed in the reverse order

You can place the same class to the stack several times.

The order of definitions is important. The request is processed by middleware in the order from root to operation, and the response will be processed in reverse order -- from operation to the root.