停止之前过滤器仍然继续进行过滤后

时间:2013-06-26 23:05:03

标签: ruby sinatra

所以我的理解是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

我在以下位置打电话给'get':localhost:4567/partners/v1/111
我希望输出的内容:

before halt

实际输出的是什么:

before halt
i am in after /partners

所以我的问题正是如此:
1.为什么停止继续(显示达到after '/partners*'
2.为什么它会点击after '/partners*'而不是before '/partners*'

1 个答案:

答案 0 :(得分:1)

Here is the code for halthere is the code for invokeinvoke下面是the method declaration for dispatch!

如您所见,dispatch!调用invoke,它运行路径块并支持halt。它还会在:before块中运行invoke过滤器。

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*')不会运行。