2014-03-05 56 views
2

我正在嘗試一個機架中間件,在單獨的層中進行身份驗證。 問題是,所有的請求都通過這個層。我不希望像CSS的資產要求,javascript中要經過認證的中間件, 我也不想退出流通要經過這個,Ruby on rails - 機架中間件排除 - 有可能嗎?

在application.rb中

config.middleware.use AuthClient::MyFilterClass 

我期待像

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

有什麼方法可以從中間件中排除自定義路徑/操作?

回答

7

機架中間件形成上下堆疊,就像下面的例子:

rack middleware

這意味着,無論請求您的決策,它會通過所有的中間件不管。
所以你不能排除這樣的中間件。

雖然你可以做的是將自己的中間件注入堆棧,它將檢查請求路徑並調用其他一些中間件。

事情是這樣的:

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 

這將調用AuthClient::MyFilterClass中間件conditionnally根據請求路徑。

+0

現在middlew寶石將意識到正在使用它的Rails應用程序。假設這個中間件被多個Rails應用使用。第二個應用中的「資產」可能具有不同的含義,可能需要進行身份驗證。通過在Rails應用程序(application.rb)中排除模式,我們可以更好地控制中間件。你怎麼看 ? –

+0

只需爲不同的應用程序編寫不同的中間件即可。 –

0

這是我的發現,在這個問題上工作時:

  1. Rack中間件沒有任何可行性,處理一個排除模式/排除的行動注入,

我同意達。 。MATHIEU,在極端情況下,我們可以通過基於請求對象過濾實現, 這裏是我的代碼示例:

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