before filters can modify request routing variables

Execute the before filters before looking up the
event. Makes it possible for filters to rewrite request
variables such as PATH_INFO and REQUEST_METHOD and have
it effect which route is chosen.
This commit is contained in:
Ryan Tomayko 2008-09-07 05:02:10 -07:00
parent 3105f21132
commit 491023a17b
2 changed files with 51 additions and 7 deletions

View File

@ -790,7 +790,11 @@ module Sinatra
attr_accessor :request, :response
attr_accessor :route_params
def initialize(request, response, route_params)
@params = nil
@data = nil
@request = request
@response = response
@route_params = route_params
@ -808,10 +812,13 @@ module Sinatra
end
def params
@params ||= begin
h = Hash.new {|h,k| h[k.to_s] if Symbol === k}
h.merge(@route_params.merge(@request.params))
end
@params ||=
begin
hash = Hash.new {|h,k| h[k.to_s] if Symbol === k}
hash.merge! @request.params
hash.merge! @route_params
hash
end
end
def data
@ -830,6 +837,11 @@ module Sinatra
request.env['rack.session'] ||= {}
end
def reset!
@params = nil
@data = nil
end
private
def method_missing(name, *args, &b)
@ -1230,13 +1242,15 @@ module Sinatra
# +env+ argument and return value.
def dispatch(env)
request = Rack::Request.new(env)
result = lookup(request)
context = EventContext.new(request, Rack::Response.new, result.params)
context.status(result.status)
context = EventContext.new(request, Rack::Response.new([], 200), {})
begin
returned =
catch(:halt) do
filters[:before].each { |f| context.instance_eval(&f) }
result = lookup(context.request)
context.route_params = result.params
context.response.status = result.status
context.reset!
[:complete, context.instance_eval(&result.block)]
end
body = returned.to_result(context)

30
test/filter_test.rb Normal file
View File

@ -0,0 +1,30 @@
require File.dirname(__FILE__) + '/helper'
context "before filters" do
setup do
Sinatra.application = nil
@app = Sinatra.application
end
specify "should be executed in the order defined" do
invoked = 0x0
@app.before { invoked = 0x01 }
@app.before { invoked |= 0x02 }
@app.get('/') { 'Hello World' }
get_it '/'
should.be.ok
body.should.be == 'Hello World'
invoked.should.be == 0x03
end
specify "should be capable of modifying the request" do
@app.get('/foo') { 'foo' }
@app.get('/bar') { 'bar' }
@app.before { request.path_info = '/bar' }
get_it '/foo'
should.be.ok
body.should.be == 'bar'
end
end