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
def self.custom_encoding_for(action, param) # :nodoc:
def self.action_encoding_template(action) # :nodoc:
false
end

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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