avoid calling custom_encoding_for when unused

if the action does not use a custom encoding, then we can skip checking if we need to fix the encoding on any of the parameters.

Instead of asking the controller about each of the parameters, we can ask the controller to tell us what params to convert once. If the controller returns nothing, we have no work to do.
This commit is contained in:
HParker 2020-10-27 09:48:55 -07:00
parent ad0b10f6c3
commit 9a2f63acbc
5 changed files with 26 additions and 10 deletions

View File

@ -135,7 +135,7 @@ module ActionController
end end
end end
def self.custom_encoding_for(action, param) # :nodoc: def self.action_encoding_template(action) # :nodoc:
false false
end end

View File

@ -15,8 +15,10 @@ module ActionController
@_parameter_encodings = Hash.new { |h, k| h[k] = {} } @_parameter_encodings = Hash.new { |h, k| h[k] = {} }
end end
def custom_encoding_for(action, param) # :nodoc: def action_encoding_template(action) # :nodoc:
@_parameter_encodings[action.to_s][param.to_s] if @_parameter_encodings.has_key?(action.to_s)
@_parameter_encodings[action.to_s]
end
end end
# Specify that a given action's parameters should all be encoded as # Specify that a given action's parameters should all be encoded as

View File

@ -76,7 +76,7 @@ module ActionDispatch
PASS_NOT_FOUND = Class.new { # :nodoc: PASS_NOT_FOUND = Class.new { # :nodoc:
def self.action(_); self; end def self.action(_); self; end
def self.call(_); [404, { "X-Cascade" => "pass" }, []]; 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 def controller_class

View File

@ -80,20 +80,19 @@ module ActionDispatch
class CustomParamEncoder # :nodoc: class CustomParamEncoder # :nodoc:
def self.encode(request, params, controller, action) 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| params.except(:controller, :action).each do |key, value|
ActionDispatch::Request::Utils.each_param_value(value) do |param| ActionDispatch::Request::Utils.each_param_value(value) do |param|
if desired_encoding = custom_encoding_for(request, controller, action, key) if encoding_template[key.to_s]
param.force_encoding(desired_encoding) param.force_encoding(encoding_template[key.to_s])
end end
end end
end end
params params
end end
def self.custom_encoding_for(request, controller, action, param) def self.action_encoding_template(request, controller, action) # :nodoc:
request.controller_class_for(controller).custom_encoding_for(action, param) request.controller_class_for(controller).action_encoding_template(action)
rescue MissingController rescue MissingController
nil nil
end end

View File

@ -4607,6 +4607,21 @@ class TestInvalidUrls < ActionDispatch::IntegrationTest
assert_response :ok assert_response :ok
end end
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 end
class TestOptionalRootSegments < ActionDispatch::IntegrationTest class TestOptionalRootSegments < ActionDispatch::IntegrationTest