diff --git a/lib/active_resource/base.rb b/lib/active_resource/base.rb index abb90acfd4..c38ba7892e 100644 --- a/lib/active_resource/base.rb +++ b/lib/active_resource/base.rb @@ -772,7 +772,7 @@ def element_path(id, prefix_options = {}, query_options = nil) check_prefix_options(prefix_options) prefix_options, query_options = split_options(prefix_options) if query_options.nil? - "#{prefix(prefix_options)}#{collection_name}/#{URI.parser.escape id.to_s}#{format_extension}#{query_string(query_options)}" + "#{prefix(prefix_options)}#{collection_name}/#{URI.encode_www_form_component(id.to_s)}#{format_extension}#{query_string(query_options)}" end # Gets the element url for the given ID in +id+. If the +query_options+ parameter is omitted, Rails diff --git a/test/cases/base_test.rb b/test/cases/base_test.rb index 3872e715d5..f9818608cb 100644 --- a/test/cases/base_test.rb +++ b/test/cases/base_test.rb @@ -688,7 +688,7 @@ def test_custom_element_path assert_equal "/people/1/addresses/1.json", StreetAddress.element_path(1, person_id: 1) assert_equal "/people/1/addresses/1.json", StreetAddress.element_path(1, "person_id" => 1) assert_equal "/people/Greg/addresses/1.json", StreetAddress.element_path(1, "person_id" => "Greg") - assert_equal "/people/ann%20mary/addresses/ann%20mary.json", StreetAddress.element_path(:'ann mary', "person_id" => "ann mary") + assert_equal "/people/ann%20mary/addresses/ann+mary.json", StreetAddress.element_path(:'ann mary', "person_id" => "ann mary") end def test_custom_element_path_without_required_prefix_param diff --git a/test/cases/finder_test.rb b/test/cases/finder_test.rb index cc49cd4051..82e081de78 100644 --- a/test/cases/finder_test.rb +++ b/test/cases/finder_test.rb @@ -172,4 +172,20 @@ def test_find_single_by_symbol_from david = Person.find(:one, from: :leader) assert_equal "David", david.name end + + def test_find_identifier_encoding + ActiveResource::HttpMock.respond_to { |m| m.get "/people/%3F.json", {}, @david } + + david = Person.find("?") + + assert_equal "David", david.name + end + + def test_find_identifier_encoding_for_path_traversal + ActiveResource::HttpMock.respond_to { |m| m.get "/people/..%2F.json", {}, @david } + + david = Person.find("../") + + assert_equal "David", david.name + end end