Created
September 21, 2009 04:08
-
-
Save purplefoot/190061 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Custom ParamsParser that can digest "multipart/related" requests | |
# to use, replace default Rails "ActionController::ParamsParser" middleware via: | |
# ActionController::Dispatcher.middleware.swap 'ActionController::ParamsParser', MultipartRelatedParamsParser | |
class MultipartRelatedParamsParser | |
ActionController::Base.param_parsers[Mime::XML] = :xml_simple | |
ActionController::Base.param_parsers[Mime::JSON] = :json | |
def initialize(app) | |
@app = app | |
end | |
def call(env) | |
if params = parse_formatted_parameters(env) | |
env["action_controller.request.request_parameters"] = params | |
end | |
@app.call(env) | |
end | |
private | |
def parse_formatted_parameters(env) | |
request = Rack::Request.new(env) | |
return false if request.content_length.to_i.zero? | |
mime_type = content_type_from_legacy_post_data_format_header(env) || request.content_type | |
strategy = ActionController::Base.param_parsers[mime_type] | |
if request.content_type =~ /^multipart\/related/ | |
strategy = :multipart_related | |
end | |
return false unless strategy | |
case strategy | |
when Proc | |
strategy.call(request.raw_post) | |
when :xml_simple, :xml_node | |
body = request.raw_post | |
body.blank? ? {} : Hash.from_xml(body).with_indifferent_access | |
when :yaml | |
YAML.load(request.raw_post) | |
when :json | |
body = request.raw_post | |
if body.blank? | |
{} | |
else | |
data = ActiveSupport::JSON.decode(body) | |
data = {:_json => data} unless data.is_a?(Hash) | |
data.with_indifferent_access | |
end | |
when :multipart_related | |
type, main_part = request.content_type.scan(/type=\"(.*)\";.*start=\"(.*)\"/).flatten | |
multipart_params = Rack::Utils::Multipart.parse_multipart(env) | |
if type == "application/xml" | |
data = Hash.from_xml(multipart_params[main_part][:tempfile].read) | |
elsif type == "application/xml" | |
data = ActiveSupport::JSON.decode(multipart_params[main_part][:temp_file].read) | |
data = {:_json => data} unless data.is_a?(Hash) | |
else | |
data = {} | |
end | |
return false if data.empty? | |
object_name = data.keys.first | |
multipart_params.reject { |key, value| key == main_part }.each do |key, value| | |
upload = value[:tempfile] | |
upload.extend(ActionController::UploadedFile) | |
upload.original_path = value[:filename] | |
upload.content_type = value[:type] | |
data[object_name][key] = upload if data.has_key?(object_name) | |
end | |
data.with_indifferent_access | |
else | |
false | |
end | |
rescue Exception => e # YAML, XML or Ruby code block errors | |
raise | |
{ "body" => request.raw_post, | |
"content_type" => request.content_type, | |
"content_length" => request.content_length, | |
"exception" => "#{e.message} (#{e.class})", | |
"backtrace" => e.backtrace } | |
end | |
def content_type_from_legacy_post_data_format_header(env) | |
if x_post_format = env['HTTP_X_POST_DATA_FORMAT'] | |
case x_post_format.to_s.downcase | |
when 'yaml' | |
return Mime::YAML | |
when 'xml' | |
return Mime::XML | |
end | |
end | |
nil | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment