diff --git a/actionpack/lib/action_controller/cgi_process.rb b/actionpack/lib/action_controller/cgi_process.rb
index dcfa39fc03..edb7fb38d8 100644
--- a/actionpack/lib/action_controller/cgi_process.rb
+++ b/actionpack/lib/action_controller/cgi_process.rb
@@ -72,7 +72,7 @@ module ActionController #:nodoc:
end
def request_parameters
- @request_parameters ||= self.class.parse_formatted_request_parameters(body, content_type_with_parameters, content_length, env)
+ @request_parameters ||= parse_formatted_request_parameters
end
def cookies
diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb
index 476f65a6dc..cdd35cc17b 100755
--- a/actionpack/lib/action_controller/request.rb
+++ b/actionpack/lib/action_controller/request.rb
@@ -231,11 +231,14 @@ module ActionController
end
- # Receive the raw post data.
- # This is useful for services such as REST, XMLRPC and SOAP
- # which communicate over HTTP POST but don't use the traditional parameter format.
+ # Read the request body. This is useful for web services that need to
+ # work with raw requests directly.
def raw_post
- @env['RAW_POST_DATA'] ||= body.read
+ unless env.include? 'RAW_POST_DATA'
+ env['RAW_POST_DATA'] = body.read(content_length)
+ body.rewind if body.respond_to?(:rewind)
+ end
+ env['RAW_POST_DATA']
end
# Returns both GET and POST parameters in a single hash.
@@ -312,37 +315,26 @@ module ActionController
end
end
-
- class << self
- def extract_content_type_without_parameters(content_type_with_parameters)
- $1.strip.downcase if content_type_with_parameters =~ /^([^,\;]*)/
- end
-
- def parse_formatted_request_parameters(body, content_type_with_parameters, content_length, env = {})
- content_length = content_length.to_i
+ def parse_formatted_request_parameters
return {} if content_length.zero?
- content_type, boundary = extract_multipart_boundary(content_type_with_parameters.to_s)
+ content_type, boundary = self.class.extract_multipart_boundary(content_type_with_parameters)
return {} if content_type.blank?
mime_type = Mime::Type.lookup(content_type)
strategy = ActionController::Base.param_parsers[mime_type]
# Only multipart form parsing expects a stream.
- if strategy && strategy != :multipart_form
- data = body.read(content_length)
- body.rewind if body.respond_to?(:rewind)
- body = data
- end
+ body = raw_post if strategy && strategy != :multipart_form
case strategy
when Proc
strategy.call(body)
when :url_encoded_form
- clean_up_ajax_request_body! body
- parse_query_parameters(body)
+ self.class.clean_up_ajax_request_body! body
+ self.class.parse_query_parameters(body)
when :multipart_form
- parse_multipart_form_parameters(body, boundary, content_length, env)
+ self.class.parse_multipart_form_parameters(body, boundary, content_length, env)
when :xml_simple, :xml_node
body.blank? ? {} : Hash.from_xml(body).with_indifferent_access
when :yaml
@@ -359,6 +351,7 @@ module ActionController
"backtrace" => e.backtrace }
end
+ class << self
def parse_query_parameters(query_string)
return {} if query_string.blank?
@@ -402,6 +395,24 @@ module ActionController
parse_request_parameters(read_multipart(body, boundary, content_length, env))
end
+ def extract_multipart_boundary(content_type_with_parameters)
+ if content_type_with_parameters =~ MULTIPART_BOUNDARY
+ ['multipart/form-data', $1.dup]
+ else
+ extract_content_type_without_parameters(content_type_with_parameters)
+ end
+ end
+
+ def extract_content_type_without_parameters(content_type_with_parameters)
+ $1.strip.downcase if content_type_with_parameters =~ /^([^,\;]*)/
+ end
+
+ def clean_up_ajax_request_body!(body)
+ body.chop! if body[-1] == 0
+ body.gsub!(/&_=$/, '')
+ end
+
+
private
def get_typed_value(value)
case value
@@ -454,20 +465,6 @@ module ActionController
MULTIPART_BOUNDARY = %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n
- def extract_multipart_boundary(content_type_with_parameters)
- if content_type_with_parameters =~ MULTIPART_BOUNDARY
- ['multipart/form-data', $1.dup]
- else
- extract_content_type_without_parameters(content_type_with_parameters)
- end
- end
-
- def clean_up_ajax_request_body!(body)
- body.chop! if body[-1] == 0
- body.gsub!(/&_=$/, '')
- end
-
-
EOL = "\015\012"
def read_multipart(body, boundary, content_length, env)
diff --git a/actionpack/test/controller/request_test.rb b/actionpack/test/controller/request_test.rb
index 4ec31b389c..4a43091823 100644
--- a/actionpack/test/controller/request_test.rb
+++ b/actionpack/test/controller/request_test.rb
@@ -708,9 +708,7 @@ class MultipartRequestParameterParsingTest < Test::Unit::TestCase
private
def process(name)
File.open(File.join(FIXTURE_PATH, name), 'rb') do |file|
- content_length = file.stat.size.to_s
- content_type = 'multipart/form-data, boundary=AaB03x'
- ActionController::AbstractRequest.parse_formatted_request_parameters(file, content_type, content_length)
+ ActionController::AbstractRequest.parse_multipart_form_parameters(file, 'AaB03x', file.stat.size, {})
end
end
end
@@ -718,9 +716,7 @@ end
class XmlParamsParsingTest < Test::Unit::TestCase
def test_single_file
- body = "David#{Base64.encode64('ABC')}"
-
- person = ActionController::AbstractRequest.parse_formatted_request_parameters(StringIO.new(body), 'application/xml', body.size)
+ person = parse_body("David#{Base64.encode64('ABC')}")
assert_equal "image/jpg", person['person']['avatar'].content_type
assert_equal "me.jpg", person['person']['avatar'].original_filename
@@ -728,7 +724,7 @@ class XmlParamsParsingTest < Test::Unit::TestCase
end
def test_multiple_files
- body = <<-end_body
+ person = parse_body(<<-end_body)
David
@@ -738,8 +734,6 @@ class XmlParamsParsingTest < Test::Unit::TestCase
end_body
- person = ActionController::AbstractRequest.parse_formatted_request_parameters(StringIO.new(body), 'application/xml', body.size)
-
assert_equal "image/jpg", person['person']['avatars']['avatar'].first.content_type
assert_equal "me.jpg", person['person']['avatars']['avatar'].first.original_filename
assert_equal "ABC", person['person']['avatars']['avatar'].first.read
@@ -748,4 +742,12 @@ class XmlParamsParsingTest < Test::Unit::TestCase
assert_equal "you.gif", person['person']['avatars']['avatar'].last.original_filename
assert_equal "DEF", person['person']['avatars']['avatar'].last.read
end
+
+ private
+ def parse_body(body)
+ env = { 'CONTENT_TYPE' => 'application/xml',
+ 'CONTENT_LENGTH' => body.size.to_s }
+ cgi = ActionController::Integration::Session::MockCGI.new(env, body)
+ ActionController::CgiRequest.new(cgi).request_parameters
+ end
end