rails: unable to re-insert middleware that was previously deleted with middleware.delete

Occasionally there may be a need to change the order of the middleware stack. In Rails 4.2 I did this by deleting a given middleware and adding it back in the new desired location. In Rails 5, it is not possible to add a previously deleted middleware, since the delete operations run after all other operations, regardless of the actual order the operations are specified. I believe this is an unintended consequence from #18994.

Steps to reproduce

  1. Delete a middleware: config.middleware.delete SomeMiddleware
  2. Re-insert the middleware somewhere else: config.middleware.use SomeMiddleware

Expected behavior

SomeMiddleware should be part of the middleware stack.

Actual behavior

SomeMiddleware is not part of the middleware stack.

System configuration

Rails version: 5.0.0.1

Ruby version: 2.2.5

About this issue

  • Original URL
  • State: open
  • Created 8 years ago
  • Reactions: 1
  • Comments: 15 (8 by maintainers)

Commits related to this issue

Most upvoted comments

@Sirupsen

Yeah that looks like a viable workaround.

Regarding the pass-through middleware I mentioned, it turns out you can substitute any object you want (even nil) as long you delete it from the stack. In other words, it doesn’t actually have to be a special pass-through middleware because you can remove it:

config.middleware.swap(MiddlewareToChangeOrderingOf, nil)
config.middleware.delete(nil)
config.middleware.insert_after(SomeOtherMiddleware, MiddlewareToChangeOrderingOf)

I think this issue (at least the original intention) has been solved after https://github.com/rails/rails/pull/38169 introduced the move_before and move_after methods?

FWIW my work-around for this issue to get Rails 4 behaviour:

session_operations = Rails::Configuration::MiddlewareStackProxy.new([
   [:delete, %w(MiddleWareToChangeOrderingOf)],
   [:insert_after, %w(SomeOtherMiddleware MiddleWareToChangeOrderingOf)],
])

config.middleware = config.middleware + session_operations

This avoids the pass-through middleware @naw suggested, although that’s a pretty clever hack 😃