Skip to content

Commit

Permalink
Raise ArgumentError if an invalid method is specified as part of a ro…
Browse files Browse the repository at this point in the history
…ute's conditions. Also raise an error if HEAD is specified as the method, as rails routes all HEAD requests through the equivalent GET, though doesn't return the response body [#182 state:resolved]

Signed-off-by: Joshua Peek <josh@joshpeek.com>
  • Loading branch information
tomafro authored and josh committed Jul 19, 2008
1 parent c3d1fda commit d394850
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 4 deletions.
9 changes: 5 additions & 4 deletions actionpack/lib/action_controller/resources.rb
Expand Up @@ -307,13 +307,13 @@ def initialize(entity, options)
# map.resources :tags, :path_prefix => '/toys/:toy_id', :name_prefix => 'toy_'
#
# You may also use <tt>:name_prefix</tt> to override the generic named routes in a nested resource:
#
#
# map.resources :articles do |article|
# article.resources :comments, :name_prefix => nil
# end
#
# end
#
# This will yield named resources like so:
#
#
# comments_url(@article)
# comment_url(@article, @comment)
#
Expand Down Expand Up @@ -559,6 +559,7 @@ def add_conditions_for(conditions, method)
def action_options_for(action, resource, method = nil)
default_options = { :action => action.to_s }
require_id = !resource.kind_of?(SingletonResource)

case default_options[:action]
when "index", "new"; default_options.merge(add_conditions_for(resource.conditions, method || :get)).merge(resource.requirements)
when "create"; default_options.merge(add_conditions_for(resource.conditions, method || :post)).merge(resource.requirements)
Expand Down
15 changes: 15 additions & 0 deletions actionpack/lib/action_controller/routing/builder.rb
Expand Up @@ -76,6 +76,8 @@ def divide_route_options(segments, options)
defaults = (options.delete(:defaults) || {}).dup
conditions = (options.delete(:conditions) || {}).dup

validate_route_conditions(conditions)

path_keys = segments.collect { |segment| segment.key if segment.respond_to?(:key) }.compact
options.each do |key, value|
hash = (path_keys.include?(key) && ! value.is_a?(Regexp)) ? defaults : requirements
Expand Down Expand Up @@ -198,6 +200,19 @@ def build(path, options)

route
end

private
def validate_route_conditions(conditions)
if method = conditions[:method]
if method == :head
raise ArgumentError, "HTTP method HEAD is invalid in route conditions. Rails processes HEAD requests the same as GETs, returning just the response headers"
end

unless HTTP_METHODS.include?(method.to_sym)
raise ArgumentError, "Invalid HTTP method specified in route conditions: #{conditions.inspect}"
end
end
end
end
end
end
20 changes: 20 additions & 0 deletions actionpack/test/controller/resources_test.rb
Expand Up @@ -516,6 +516,26 @@ def test_should_not_allow_delete_or_put_on_collection_path
end
end

def test_should_not_allow_invalid_head_method_for_member_routes
with_routing do |set|
set.draw do |map|
assert_raises(ArgumentError) do
map.resources :messages, :member => {:something => :head}
end
end
end
end

def test_should_not_allow_invalid_http_methods_for_member_routes
with_routing do |set|
set.draw do |map|
assert_raises(ArgumentError) do
map.resources :messages, :member => {:something => :invalid}
end
end
end
end

def test_resource_action_separator
with_routing do |set|
set.draw do |map|
Expand Down
16 changes: 16 additions & 0 deletions actionpack/test/controller/routing_test.rb
Expand Up @@ -1801,6 +1801,22 @@ def test_route_requirements_with_anchor_chars_are_invalid
end
end

def test_route_requirements_with_invalid_http_method_is_invalid
assert_raises ArgumentError do
set.draw do |map|
map.connect 'valid/route', :controller => 'pages', :action => 'show', :conditions => {:method => :invalid}
end
end
end

def test_route_requirements_with_head_method_condition_is_invalid
assert_raises ArgumentError do
set.draw do |map|
map.connect 'valid/route', :controller => 'pages', :action => 'show', :conditions => {:method => :head}
end
end
end

def test_non_path_route_requirements_match_all
set.draw do |map|
map.connect 'page/37s', :controller => 'pages', :action => 'show', :name => /(jamis|david)/
Expand Down

1 comment on commit d394850

@matthewrudy
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tomafro – you should go to bed instead of submitting patches.

Please sign in to comment.