Make rails middlewares reusable outside of rails

This can be considered chore/feature.

As of now, Rails middlewares are unusable outside of a Rails app. I've been
trying to use Rack::URLMap to map subpaths to different apps:

app =
  "/" => Rails.application,
  "/api" => App::API

run app

this works, but I lose all the middlewares of the rails app, one of them
being the authentication layer, which is handled by devise.

so I went further and have been trying to do something like this:

class CustomBuilder < Rack::Builder
  def call(env)
    req = Rails.application.send(:build_request, env)

api = do
  run App::APIend
# ugly, but rack doesn't allow me anything else
api.instance_variable_get(:@use, Rack.application.config.middleware)

app =
  "/" => Rails.application,
  "/api" => api

This will break, because Rack::Builder#to_app requires the middleware to be
<>. From
the same link, you can see that the middleware must respond to [].

The first approach seems to be to implement
ActionDispatch::MiddlewareStack#reverse (it is an Enumerable, not an
Array), and to implement ActionDispatch::MiddlewareStack::Middleware#[](could
be a simple alias to ActionDispatch::MiddlewareStack::Middleware#build).
The #reverseimplementation is however "dangerous", because it means that
existing #use calls which do global mutation will be executed as many times
as the number of apps mapped in my Rack::URLMap app. This is why this would
break <>, but then
again, the requirement is from rack, so maybe this could be deviced there.

Rails version:

I’ve started a pull request in rack:, with the goal to support suck a feature. According to the spec, the middleware stack would have to implement the #to_app method. The other necessity would be to make the Rails.appliction.build_request a public method, as non-rails apps would have to have the env pre-initialized for its custom rack middlewares.