From 8e84e0c60c61ce66d895e3b8ccb3ec22c5981211 Mon Sep 17 00:00:00 2001 From: Mike Pastore Date: Wed, 10 Feb 2016 00:12:17 -0600 Subject: [PATCH] Fix issue with passed routes and provides --- lib/sinatra/base.rb | 13 +++++++++++-- test/routing_test.rb | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/lib/sinatra/base.rb b/lib/sinatra/base.rb index 7f182e2907..25cac87027 100644 --- a/lib/sinatra/base.rb +++ b/lib/sinatra/base.rb @@ -882,6 +882,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 @@ -956,15 +957,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, keys, conditions, block| + @response['Content-Type'] = nil unless @pinned_response + returned_pass_block = process_route(pattern, keys, conditions) do |*args| env['sinatra.route'] = block.instance_variable_get(:@route_name) route_eval { block[*args] } @@ -1080,7 +1087,9 @@ def invoke 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 diff --git a/test/routing_test.rb b/test/routing_test.rb index 5756731268..4c20f8028e 100644 --- a/test/routing_test.rb +++ b/test/routing_test.rb @@ -1063,6 +1063,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']