Reputation: 23
So my understanding is that the halt command should stop the request in the current filter, but it appears to continue on. What follows is a very simple Sinatra app demonstrating this.
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
I am calling 'get' on the following location: localhost:4567/partners/v1/111
What I expect to output:
before halt
What is actually outputting:
before halt
i am in after /partners
So my question's are exactly:
1. Why does the halt continue on at all (shown with it reaching after '/partners*'
)
2. Why does it hit the after '/partners*'
but not the before '/partners*'
Upvotes: 2
Views: 531
Reputation: 12251
Here is the code for halt
and here is the code for invoke
, and just below invoke
is the method declaration for dispatch!
As you can see, dispatch!
calls invoke
, which runs the route block with support for halt
ing. It also runs the :before
filter in the invoke
block.
invoke do
static! if settings.static? && (request.get? || request.head?)
filter! :before
route!
So you can halt
inside a before
filter and it won't reach the route, which is why you don't see any output from your route block.
However, the dispatch!
method also has an ensure
:
ensure
begin
filter! :after unless env['sinatra.static_file']
An ensure
does what it says, it will always be evaluated. This is why the after '/partners*'
block is processed. This is expected behaviour (as it's coded quite clearly that way). Basically, if you put in an after
block, it will get processed, regardless of halt
s in before
filters or route blocks.
From the docs:
Routes are matched in the order they are defined. The first route that matches the request is invoked.
…filters are evaluated before each request within the same context as the routes
Now, the docs aren't explicit about this, but if you add the two quotes together I'd take that to mean "Filters are matched in the order they are defined." Basically, because it fits the actual behaviour.
All the before
filters should run, but you put a halt
in the first one, so the second one (before '/partners*'
) doesn't run.
Upvotes: 1