2

I am trying a rack middleware, to do authentication in a separate layer. The problem is, all request goes through this layer. I don't want the asset request like css, javascript to go through authentication middleware., I also don't want logout flow to go through this.,

In application.rb

config.middleware.use AuthClient::MyFilterClass

I am expecting something like

config.middleware.use AuthClient::MyFilterClass, :exclude => [:logout,'*/assets/*']

Is there any way to exclude custom path / actions from middleware ?

Sairam Krish
  • 10,158
  • 3
  • 55
  • 67

2 Answers2

9

Rack middlewares form a up and down stack, like the following example:

rack middleware

This means that whatever the request your making, it will pass through all middlewares no matter what.
So you can't exclude middlewares like this.

What you can do though, is inject your own middleware to the stack, which will check the request path and call some other middlewares or not.

Something like this:

class MyMiddleware
  def initialize(app)
    @app = app
  end

  def call(env)
    if env['REQUEST_PATH'].match(/^\/assets\//)
      middleware = AuthClient::MyFilterClass.new(@app)
      env = middleware.call(env)
    end

    @app.call(env)
  end
end

This will call the AuthClient::MyFilterClass middleware conditionnally depending of the request path.

Community
  • 1
  • 1
Damien MATHIEU
  • 31,924
  • 13
  • 86
  • 94
  • Now the middleware gem will be aware of the rails app which is using it. Let's say this middleware is used by more than one rails app. '/assets' in second app may have a different meaning and it may need authentication to happen. By having the pattern to exclude in the rails app (application.rb) we can have finer control on the middleware. What do you think ? – Sairam Krish Mar 05 '14 at 13:32
  • Just write different middlewares for different apps. – Damien MATHIEU Mar 05 '14 at 14:02
0

These are my findings, while working on this issue :

  1. Rack middleware doesn't have any feasibility to handle an exclude pattern / exclude action injection.,

I agree with Damien MATHIEU., In extreme case, we could achieve by filtering based on request object., Here is my code example :

def call(env)
  if (should_authenticate(env))
    //do auth related stuff
  end

  @app.call(env)
end

private
  def should_authenticate(env)
    request = Request.new(env)
    return false if request.content_length.zero?
   strategy = other_conditions(env)
   return false unless strategy

case strategy
when 'condition1'
  //conditional logic
when 'condition2'
  //conditional logic
else
  false
end
end

def other_conditions(env)
 if env['REQUEST_PATH'].match(/^\/assets\//)
   return 'condition1'
 end
//Check for other pre-validations to do
end
Sairam Krish
  • 10,158
  • 3
  • 55
  • 67