From 09d9f04d08358dc2b49fbf6bc16b58f034161abb Mon Sep 17 00:00:00 2001 From: Yves Senn Date: Tue, 26 Feb 2013 11:42:55 +0100 Subject: the router allows String contraints. Closes #9432. --- actionpack/CHANGELOG.md | 10 ++++++- actionpack/lib/action_dispatch/routing/mapper.rb | 28 ++++++++++-------- actionpack/test/dispatch/routing_test.rb | 36 ++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 12 deletions(-) diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index a9825aa3fb..4e09485918 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,10 +1,18 @@ ## Rails 4.0.0 (unreleased) ## +* Don't verify Regexp requirements for non-Regexp `:constraints`. + Fixes #9432. + + Example: + + get '/photos.:format' => 'feeds#photos', constraints: {format: 'xml'} + + *Yves Senn* + * Make `ActionDispatch::Journey::Path::Pattern#new` raise more meaningful exception message. *Thierry Zires* - ## Rails 4.0.0.beta1 (February 25, 2013) ## * Fix `respond_to` not using formats that have no block if all is present. *Michael Grosser* diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 817480c7ae..dba9ccbfa5 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -124,15 +124,7 @@ module ActionDispatch def normalize_requirements! constraints.each do |key, requirement| next unless segment_keys.include?(key) || key == :controller - - if requirement.source =~ ANCHOR_CHARACTERS_REGEX - raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}" - end - - if requirement.multiline? - raise ArgumentError, "Regexp multiline option is not allowed in routing requirements: #{requirement.inspect}" - end - + verify_regexp_requirement(requirement) if requirement.is_a?(Regexp) @requirements[key] = requirement end @@ -145,6 +137,16 @@ module ActionDispatch end end + def verify_regexp_requirement(requirement) + if requirement.source =~ ANCHOR_CHARACTERS_REGEX + raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}" + end + + if requirement.multiline? + raise ArgumentError, "Regexp multiline option is not allowed in routing requirements: #{requirement.inspect}" + end + end + def normalize_defaults! @defaults.merge!(scope[:defaults]) if scope[:defaults] @defaults.merge!(options[:defaults]) if options[:defaults] @@ -425,11 +427,15 @@ module ActionDispatch # end # # [:constraints] - # Constrains parameters with a hash of regular expressions or an - # object that responds to matches? + # Constrains parameters with a hash of regular expressions + # or an object that responds to matches?. In addition, constraints + # other than path can also be specified with any object + # that responds to === (eg. String, Array, Range, etc.). # # match 'path/:id', constraints: { id: /[A-Z]\d{5}/ } # + # match 'json_only', constraints: { format: 'json' } + # # class Blacklist # def matches?(request) request.remote_ip == '1.2.3.4' end # end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 37ad9ddb6b..22c5cf71ce 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -3380,6 +3380,42 @@ class TestPortConstraints < ActionDispatch::IntegrationTest end end +class TestFormatConstraints < ActionDispatch::IntegrationTest + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] } + + get '/string', to: ok, constraints: { format: 'json' } + get '/regexp', to: ok, constraints: { format: /json/ } + end + end + + include Routes.url_helpers + def app; Routes end + + def test_string_format_constraints + get 'http://www.example.com/string' + assert_response :success + + get 'http://www.example.com/string.json' + assert_response :success + + get 'http://www.example.com/string.html' + assert_response :not_found + end + + def test_regexp_format_constraints + get 'http://www.example.com/regexp' + assert_response :success + + get 'http://www.example.com/regexp.json' + assert_response :success + + get 'http://www.example.com/regexp.html' + assert_response :not_found + end +end + class TestRouteDefaults < ActionDispatch::IntegrationTest stub_controllers do |routes| Routes = routes -- cgit v1.2.3