diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index ada5e39ead..e6257f8c4a 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -135,7 +135,7 @@ module ActionController end end - def self.custom_encoding_for(action, param) # :nodoc: + def self.action_encoding_template(action) # :nodoc: false end diff --git a/actionpack/lib/action_controller/metal/parameter_encoding.rb b/actionpack/lib/action_controller/metal/parameter_encoding.rb index d587772536..d6d33ad8c8 100644 --- a/actionpack/lib/action_controller/metal/parameter_encoding.rb +++ b/actionpack/lib/action_controller/metal/parameter_encoding.rb @@ -15,8 +15,10 @@ module ActionController @_parameter_encodings = Hash.new { |h, k| h[k] = {} } end - def custom_encoding_for(action, param) # :nodoc: - @_parameter_encodings[action.to_s][param.to_s] + def action_encoding_template(action) # :nodoc: + if @_parameter_encodings.has_key?(action.to_s) + @_parameter_encodings[action.to_s] + end end # Specify that a given action's parameters should all be encoded as diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 36b55c950c..08c9162316 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -76,7 +76,7 @@ module ActionDispatch PASS_NOT_FOUND = Class.new { # :nodoc: def self.action(_); self; end def self.call(_); [404, { "X-Cascade" => "pass" }, []]; end - def self.custom_encoding_for(action, param); nil; end + def self.action_encoding_template(action); false; end } def controller_class diff --git a/actionpack/lib/action_dispatch/request/utils.rb b/actionpack/lib/action_dispatch/request/utils.rb index 2985849527..f298cac9d1 100644 --- a/actionpack/lib/action_dispatch/request/utils.rb +++ b/actionpack/lib/action_dispatch/request/utils.rb @@ -80,20 +80,19 @@ module ActionDispatch class CustomParamEncoder # :nodoc: def self.encode(request, params, controller, action) - return params unless controller && controller.valid_encoding? - + return params unless controller && controller.valid_encoding? && encoding_template = action_encoding_template(request, controller, action) params.except(:controller, :action).each do |key, value| ActionDispatch::Request::Utils.each_param_value(value) do |param| - if desired_encoding = custom_encoding_for(request, controller, action, key) - param.force_encoding(desired_encoding) + if encoding_template[key.to_s] + param.force_encoding(encoding_template[key.to_s]) end end end params end - def self.custom_encoding_for(request, controller, action, param) - request.controller_class_for(controller).custom_encoding_for(action, param) + def self.action_encoding_template(request, controller, action) # :nodoc: + request.controller_class_for(controller).action_encoding_template(action) rescue MissingController nil end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 96ea071531..44d45924e7 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -4607,6 +4607,21 @@ class TestInvalidUrls < ActionDispatch::IntegrationTest assert_response :ok end end + + test "does not encode params besides id" do + with_routing do |set| + set.draw do + get "/foo/show(/:id)", to: "test_invalid_urls/foo#show" + get "/bar/show(/:id)", controller: "test_invalid_urls/foo", action: "show" + end + + get "/foo/show/%E2%EF%BF%BD%A6?something_else=%E2%EF%BF%BD%A6" + assert_response :bad_request + + get "/foo/show/%E2%EF%BF%BD%A6?something_else=%E2%EF%BF%BD%A6" + assert_response :bad_request + end + end end class TestOptionalRootSegments < ActionDispatch::IntegrationTest