module Roda::RodaPlugins::Middleware

The middleware plugin allows the Roda app to be used as rack middleware.

In the example below, requests to /mid will return Mid by the Mid middleware, and requests to /app will not be matched by the Mid middleware, so they will be forwarded to App.

class Mid < Roda
  plugin :middleware

  route do |r|
    r.is "mid" do
      "Mid"
    end
  end
end

class App < Roda
  use Mid

  route do |r|
    r.is "app" do
      "App"
    end
  end
end

run App

By default, when the app is used as middleware and handles the request at all, it does not forward the request to the next middleware. For the following setup:

class Mid < Roda
  plugin :middleware

  route do |r|
    r.on "foo" do
      r.is "mid" do
        "Mid"
      end
    end
  end
end

class App < Roda
  use Mid

  route do |r|
    r.on "foo" do
      r.is "app" do
        "App"
      end
    end
  end
end

run App

Requests for +/foo/mid will+ return Mid, but requests for /foo/app will return an empty 404 response, because the middleware handles the /foo/app request in the r.on "foo" do block, but does not have the block return a result, which Roda treats as an empty 404 response. If you would like the middleware to forward /foo/app request to the application, you should use the :next_if_not_found plugin option.

It is possible to use the Roda app as a regular app even when using the middleware plugin. Using an app as middleware automatically creates a subclass of the app for the middleware. Because a subclass is automatically created when the app is used as middleware, any configuration of the app should be done before using it as middleware instead of after.

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"