2013-06-26 71 views
2

所以我的理解是halt命令應該停止當前過濾器中的請求,但它似乎繼續。接下來是一個非常簡單的Sinatra應用程序,展示了這一點。暫停過濾器仍然繼續之前過濾器

server.rb

require 'sinatra' 

before do 
    puts "before halt" 
    halt 401 
    puts "after halt" 
end 

before '/partners*' do 
    puts "i am in before /partners" 
end 

after '/partners*' do 
    puts "i am in after /partners" 
end 

get '/partners/v1/:public_id' do 
    puts "i am in the actual route" 
end 

我打電話 '得到' 在以下位置:localhost:4567/partners/v1/111
我希望能輸出什麼:

before halt 

什麼實際輸出:

before halt 
i am in after /partners 

所以我的問題是:
1.爲什麼停止繼續在所有(用它達到after '/partners*'
2.爲什麼它擊中了after '/partners*'但不是before '/partners*'

+0

我的猜測是你不能在前面的句子中「停頓」,也許問起sinatra的開發者關於它,也許這是意想不到的... – rogerdpack

回答

1

Here is the code for halthere is the code for invoke,僅低於invokethe method declaration for dispatch!

如您所見,dispatch!調用invoke,它運行支持halt ing的路由塊。它還在invoke塊中運行:before篩選器。

invoke do 
    static! if settings.static? && (request.get? || request.head?) 
    filter! :before 
    route! 

所以,你可以halt一個before過濾器內部,也不會到達的路線,這就是爲什麼你沒有看到你的路線區塊任何輸出。

然而,dispatch!方法也有一個ensure

ensure 
    begin 
    filter! :after unless env['sinatra.static_file'] 

ensure做什麼它說,它總是會被評估。這就是處理after '/partners*'塊的原因。這是預期的行爲(因爲它的編碼方式很清楚)。基本上,如果你輸入一個after塊,它將被處理,無論halt是否在before過濾器或路由塊。

從文檔:

路線中定義它們的順序是匹配的。匹配請求的第一條路由被調用。

and

...過濾器在同一範圍內的每個請求的路線

現在,文檔是不明確的有關此之前評估,但如果你將兩個引用在一起我會認爲「過濾器按照它們定義的順序進行匹配」。基本上,因爲它符合實際的行爲。

所有的before過濾器都應該運行,但是您在第一個過程中放置​​了一個halt,因此第二個過濾器(before '/partners*')不運行。

+0

有趣的是,這意味着我不應該做任何事情後,有依賴關係的過濾器在過濾器之前。在我看來,這有點不直觀,但你的文檔確實清楚地說明了它的正確性。謝謝! –

+0

@TylerA是的,我認爲你是對的。如果你記住'throw' /'catch'停止了所有的處理,'halt'是一個鬆散的同義詞,而'after'過濾器是''ensure''的一個鬆散的同義詞,那麼你就會擁有它的權利。很高興我能幫上忙。 – iain

相關問題