2

所以我的理解是停止命令应该停止当前过滤器中的请求,但它似乎继续。下面是一个非常简单的 Sinatra 应用程序来演示这一点。

服务器.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*'

4

1 回答 1

1

这是代码halt这里是代码invoke,下面invoke方法声明dispatch!

如您所见,dispatch!调用invoke,它运行支持halting 的路由块。它还在块中运行:before过滤器。invoke

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

因此,您可以haltbefore过滤器内部并且它不会到达路由,这就是为什么您看不到路由块的任何输出的原因。

但是,该dispatch!方法也有一个ensure

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

Anensure言行一致,它总是会被评估。这就是after '/partners*'处理块的原因。这是预期的行为(因为它的编码非常清楚)。基本上,如果您放入一个after块,它将被处理,无论过滤器或路由块中的halts 是什么。before

从文档:

路由按照定义的顺序进行匹配。调用与请求匹配的第一个路由。

…过滤器在与路由相同的上下文中的每个请求之前进行评估

现在,文档并没有明确说明这一点,但是如果将两个引号加在一起,我会认为这意味着“过滤器按照定义的顺序匹配”。基本上,因为它符合实际行为。

所有before过滤器都应该运行,但是您halt在第一个过滤器中添加了 a,因此第二个过滤器 ( before '/partners*') 不会运行。

于 2013-06-27T00:09:35.510 回答