Skip to content

Commit

Permalink
Fix issue with passed routes and provides (#1606)
Browse files Browse the repository at this point in the history
  • Loading branch information
jkowens committed Mar 16, 2020
1 parent 00bdf4f commit ecf687d
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 2 deletions.
13 changes: 11 additions & 2 deletions lib/sinatra/base.rb
Expand Up @@ -924,6 +924,7 @@ def initialize(app = nil)
super()
@app = app
@template_cache = Tilt::Cache.new
@pinned_response = nil # whether a before! filter pinned the content-type
yield self if block_given?
end

Expand Down Expand Up @@ -997,15 +998,21 @@ def forward
private

# Run filters defined on the class and all superclasses.
# Accepts an optional block to call after each filter is applied.
def filter!(type, base = settings)
filter! type, base.superclass if base.superclass.respond_to?(:filters)
base.filters[type].each { |args| process_route(*args) }
base.filters[type].each do |args|
result = process_route(*args)
yield result if block_given?
end
end

# Run routes defined on the class and all superclasses.
def route!(base = settings, pass_block = nil)
if routes = base.routes[@request.request_method]
routes.each do |pattern, conditions, block|
@response['Content-Type'] = nil unless @pinned_response

returned_pass_block = process_route(pattern, conditions) do |*args|
env['sinatra.route'] = "#{@request.request_method} #{pattern}"
route_eval { block[*args] }
Expand Down Expand Up @@ -1121,7 +1128,9 @@ def dispatch!

invoke do
static! if settings.static? && (request.get? || request.head?)
filter! :before
filter! :before do
@pinned_response = !@response['Content-Type'].nil?
end
route!
end
rescue ::Exception => boom
Expand Down
22 changes: 22 additions & 0 deletions test/routing_test.rb
Expand Up @@ -1212,6 +1212,28 @@ class RoutingTest < Minitest::Test
assert_body 'html'
end

it "doesn't allow provides of passed routes to interfere with provides of other routes" do
mock_app do
get('/:foo', :provides => :txt) do
pass if params[:foo] != 'foo'

'foo'
end

get('/bar', :provides => :html) { 'bar' }
end

get '/foo', {}, { 'HTTP_ACCEPT' => '*/*' }
assert ok?
assert_equal 'text/plain;charset=utf-8', response.headers['Content-Type']
assert_body 'foo'

get '/bar', {}, { 'HTTP_ACCEPT' => '*/*' }
assert ok?
assert_equal 'text/html;charset=utf-8', response.headers['Content-Type']
assert_body 'bar'
end

it "allows multiple mime types for accept header" do
types = ['image/jpeg', 'image/pjpeg']

Expand Down

0 comments on commit ecf687d

Please sign in to comment.