Sairam Krish
Sairam Krish

Reputation: 11751

Ruby on rails - rack middleware exclude - is it possible?

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 ?

Upvotes: 2

Views: 2419

Answers (2)

Sairam Krish
Sairam Krish

Reputation: 11751

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

Upvotes: 0

Damien MATHIEU
Damien MATHIEU

Reputation: 32629

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.

Upvotes: 9

Related Questions