aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/lib/action_controller/test_case.rb115
-rw-r--r--actionpack/lib/action_dispatch.rb1
-rw-r--r--actionpack/lib/action_dispatch/middleware/load_interlock.rb21
-rw-r--r--actionpack/lib/action_dispatch/middleware/params_parser.rb11
4 files changed, 88 insertions, 60 deletions
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 329e321888..43c481339a 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -44,18 +44,11 @@ module ActionController
def assign_parameters(routes, controller_path, action, parameters = {})
parameters = parameters.symbolize_keys
- extra_keys = routes.extra_keys(parameters.merge(:controller => controller_path, :action => action))
- non_path_parameters = {}.with_indifferent_access
+ generated_path, extra_keys = routes.generate_extras(parameters.merge(:controller => controller_path, :action => action))
+ non_path_parameters = {}
+ path_parameters = {}
parameters.each do |key, value|
- if value.is_a?(Array) && (value.frozen? || value.any?(&:frozen?))
- value = value.map{ |v| v.duplicable? ? v.dup : v }
- elsif value.is_a?(Hash) && (value.frozen? || value.any?{ |k,v| v.frozen? })
- value = Hash[value.map{ |k,v| [k, v.duplicable? ? v.dup : v] }]
- elsif value.frozen? && value.duplicable?
- value = value.dup
- end
-
if extra_keys.include?(key) || key == :action || key == :controller
non_path_parameters[key] = value
else
@@ -74,23 +67,69 @@ module ActionController
self.query_string = non_path_parameters.to_query
end
else
- @env['action_dispatch.request.query_parameters'] = {}
- self.request_parameters = non_path_parameters
+ if ENCODER.should_multipart?(non_path_parameters)
+ @env['CONTENT_TYPE'] = ENCODER.content_type
+ data = ENCODER.build_multipart non_path_parameters
+ else
+ @env['CONTENT_TYPE'] ||= 'application/x-www-form-urlencoded'
+
+ # FIXME: setting `request_parametes` is normally handled by the
+ # params parser middleware, and we should remove this roundtripping
+ # when we switch to caling `call` on the controller
+
+ case content_mime_type.ref
+ when :json
+ data = ActiveSupport::JSON.encode(non_path_parameters)
+ params = ActiveSupport::JSON.decode(data).with_indifferent_access
+ self.request_parameters = params
+ when :xml
+ data = non_path_parameters.to_xml
+ params = Hash.from_xml(data)['hash']
+ self.request_parameters = params
+ when :url_encoded_form
+ data = non_path_parameters.to_query
+ else
+ raise "Unknown Content-Type: #{content_type}"
+ end
+ end
+
+ @env['CONTENT_LENGTH'] = data.length.to_s
+ @env['rack.input'] = StringIO.new(data)
end
+ @env["PATH_INFO"] ||= generated_path
path_parameters[:controller] = controller_path
path_parameters[:action] = action
- # Clear the combined params hash in case it was already referenced.
- @env.delete("action_dispatch.request.parameters")
+ self.path_parameters = path_parameters
+ end
+
+ ENCODER = Class.new do
+ include Rack::Test::Utils
+
+ def should_multipart?(params)
+ # FIXME: lifted from Rack-Test. We should push this separation upstream
+ multipart = false
+ query = lambda { |value|
+ case value
+ when Array
+ value.each(&query)
+ when Hash
+ value.values.each(&query)
+ when Rack::Test::UploadedFile
+ multipart = true
+ end
+ }
+ params.values.each(&query)
+ multipart
+ end
- # Clear the filter cache variables so they're not stale
- @filtered_parameters = @filtered_env = @filtered_path = nil
+ public :build_multipart
- data = request_parameters.to_query
- @env['CONTENT_LENGTH'] = data.length.to_s
- @env['rack.input'] = StringIO.new(data)
- end
+ def content_type
+ "multipart/form-data; boundary=#{Rack::Test::MULTIPART_BOUNDARY}"
+ end
+ end.new
end
class TestResponse < ActionDispatch::TestResponse
@@ -370,19 +409,6 @@ module ActionController
end
alias xhr :xml_http_request
- def paramify_values(hash_or_array_or_value)
- case hash_or_array_or_value
- when Hash
- Hash[hash_or_array_or_value.map{|key, value| [key, paramify_values(value)] }]
- when Array
- hash_or_array_or_value.map {|i| paramify_values(i)}
- when Rack::Test::UploadedFile, ActionDispatch::Http::UploadedFile
- hash_or_array_or_value
- else
- hash_or_array_or_value.to_param
- end
- end
-
# Simulate a HTTP request to +action+ by specifying request method,
# parameters and set/volley the response.
#
@@ -442,10 +468,6 @@ module ActionController
parameters ||= {}
- # Ensure that numbers and symbols passed as params are converted to
- # proper params, as is the case when engaging rack.
- parameters = paramify_values(parameters) if html_format?(parameters)
-
if format.present?
parameters[:format] = format
end
@@ -484,7 +506,7 @@ module ActionController
@controller.request = @request
@controller.response = @response
- build_request_uri(controller_class_name, action, parameters)
+ @request.env["SCRIPT_NAME"] ||= @controller.config.relative_url_root
@controller.recycle!
@controller.process(action)
@@ -559,6 +581,7 @@ module ActionController
env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ }
env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ }
env.delete 'action_dispatch.request.query_parameters'
+ env.delete 'action_dispatch.request.request_parameters'
env
end
@@ -608,22 +631,6 @@ module ActionController
end
end
- def build_request_uri(controller_class_name, action, parameters)
- unless @request.env["PATH_INFO"]
- options = @controller.respond_to?(:url_options) ? @controller.__send__(:url_options).merge(parameters) : parameters
- options.update(
- :controller => controller_class_name,
- :action => action,
- :relative_url_root => nil,
- :_recall => @request.path_parameters)
-
- url, = @routes.path_for(options).split("?", 2)
-
- @request.env["SCRIPT_NAME"] = @controller.config.relative_url_root
- @request.env["PATH_INFO"] = url
- end
- end
-
def html_format?(parameters)
return true unless parameters.key?(:format)
Mime.fetch(parameters[:format]) { Mime['html'] }.html?
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index dcd3ee0644..f6336c8c7a 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -52,6 +52,7 @@ module ActionDispatch
autoload :DebugExceptions
autoload :ExceptionWrapper
autoload :Flash
+ autoload :LoadInterlock
autoload :ParamsParser
autoload :PublicExceptions
autoload :Reloader
diff --git a/actionpack/lib/action_dispatch/middleware/load_interlock.rb b/actionpack/lib/action_dispatch/middleware/load_interlock.rb
new file mode 100644
index 0000000000..07f498319c
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/load_interlock.rb
@@ -0,0 +1,21 @@
+require 'active_support/dependencies'
+require 'rack/body_proxy'
+
+module ActionDispatch
+ class LoadInterlock
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ interlock = ActiveSupport::Dependencies.interlock
+ interlock.start_running
+ response = @app.call(env)
+ body = Rack::BodyProxy.new(response[2]) { interlock.done_running }
+ response[2] = body
+ response
+ ensure
+ interlock.done_running unless body
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb
index 3776aa78ed..e2b3b06fd8 100644
--- a/actionpack/lib/action_dispatch/middleware/params_parser.rb
+++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb
@@ -26,20 +26,19 @@ module ActionDispatch
end
def call(env)
- if params = parse_formatted_parameters(env)
- env["action_dispatch.request.request_parameters"] = params
- end
+ default = env["action_dispatch.request.request_parameters"]
+ env["action_dispatch.request.request_parameters"] = parse_formatted_parameters(env, @parsers, default)
@app.call(env)
end
private
- def parse_formatted_parameters(env)
+ def parse_formatted_parameters(env, parsers, default)
request = Request.new(env)
- return false if request.content_length.zero?
+ return default if request.content_length.zero?
- strategy = @parsers.fetch(request.content_mime_type) { return false }
+ strategy = parsers.fetch(request.content_mime_type) { return default }
strategy.call(request.raw_post)