Skip to content

Commit

Permalink
XML-formatted requests are typecast according to "type" attributes fo…
Browse files Browse the repository at this point in the history
…r :xml_simple

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3915 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information
jamis committed Mar 18, 2006
1 parent 93f8bd1 commit 459559a
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 2 deletions.
2 changes: 2 additions & 0 deletions actionpack/CHANGELOG
@@ -1,5 +1,7 @@
*SVN*

* XML-formatted requests are typecast according to "type" attributes for :xml_simple [Jamis Buck]

* Added protection against proxy setups treating requests as local even when they're not #3898 [stephen_purcell@yahoo.com]

* Added TestRequest#raw_post that simulate raw_post from CgiRequest #3042 [francois.beausoleil@gmail.com]
Expand Down
44 changes: 43 additions & 1 deletion actionpack/lib/action_controller/cgi_ext/cgi_methods.rb
Expand Up @@ -63,7 +63,11 @@ def self.parse_formatted_request_parameters(mime_type, raw_post_data)
when Proc
strategy.call(raw_post_data)
when :xml_simple
XmlSimple.xml_in(raw_post_data, 'ForceArray' => false, 'keeproot' => true)
typecast_xml_value(XmlSimple.xml_in(raw_post_data,
'forcearray' => false,
'forcecontent' => true,
'keeproot' => true,
'contentkey' => '__content__'))
when :yaml
YAML.load(raw_post_data)
when :xml_node
Expand All @@ -77,8 +81,46 @@ def self.parse_formatted_request_parameters(mime_type, raw_post_data)
"raw_post_data" => raw_post_data, "format" => mime_type }
end

def self.typecast_xml_value(value)
case value
when Hash
if value.has_key?("__content__")
content = translate_xml_entities(value["__content__"])
case value["type"]
when "integer" then content.to_i
when "boolean" then content == "true"
when "datetime" then Time.parse(content)
when "date" then Date.parse(content)
else content
end
else
value.empty? ? nil : value.inject({}) do |h,(k,v)|
h[k] = typecast_xml_value(v)
h
end
end
when Array
value.map! { |i| typecast_xml_value(i) }
case value.length
when 0 then nil
when 1 then value.first
else value
end
else
raise "can't typecast #{value.inspect}"
end
end

private

def self.translate_xml_entities(value)
value.gsub(/&lt;/, "<").
gsub(/&gt;/, ">").
gsub(/&quot;/, '"').
gsub(/&apos;/, "'").
gsub(/&amp;/, "&")
end

def self.dasherize_keys(params)
case params.class.to_s
when "Hash"
Expand Down
54 changes: 53 additions & 1 deletion actionpack/test/controller/webservice_test.rb
Expand Up @@ -106,14 +106,66 @@ def test_dasherized_keys_as_xml
ActionController::Base.param_parsers[Mime::XML] = :xml_simple
process('POST', 'application/xml', "<first-key>\n<sub-key>...</sub-key>\n</first-key>", true)
assert_equal 'action, controller, first_key(sub_key), full', @controller.response.body
assert_equal "...", @controller.params[:first_key][:sub_key]
end

def test_typecast_as_xml
ActionController::Base.param_parsers[Mime::XML] = :xml_simple
process('POST', 'application/xml', <<-XML)
<data>
<a type="integer">15</a>
<b type="boolean">false</b>
<c type="boolean">true</c>
<d type="date">2005-03-17</d>
<e type="datetime">2005-03-17T21:41:07Z</e>
<f>unparsed</f>
<g type="integer">1</g>
<g>hello</g>
<g type="date">1974-07-25</g>
</data>
XML
params = @controller.params
assert_equal 15, params[:data][:a]
assert_equal false, params[:data][:b]
assert_equal true, params[:data][:c]
assert_equal Date.new(2005,3,17), params[:data][:d]
assert_equal Time.utc(2005,3,17,21,41,7), params[:data][:e]
assert_equal "unparsed", params[:data][:f]
assert_equal [1, "hello", Date.new(1974,7,25)], params[:data][:g]
end

def test_dasherized_keys_as_yaml
ActionController::Base.param_parsers[Mime::YAML] = :yaml
process('POST', 'application/x-yaml', "---\nfirst-key:\n sub-key: ...\n", true)
assert_equal 'action, controller, first_key(sub_key), full', @controller.response.body
assert_equal "...", @controller.params[:first_key][:sub_key]
end

def test_typecast_as_yaml
ActionController::Base.param_parsers[Mime::YAML] = :yaml
process('POST', 'application/x-yaml', <<-YAML)
---
data:
a: 15
b: false
c: true
d: 2005-03-17
e: 2005-03-17T21:41:07Z
f: unparsed
g:
- 1
- hello
- 1974-07-25
YAML
params = @controller.params
assert_equal 15, params[:data][:a]
assert_equal false, params[:data][:b]
assert_equal true, params[:data][:c]
assert_equal Date.new(2005,3,17), params[:data][:d]
assert_equal Time.utc(2005,3,17,21,41,7), params[:data][:e]
assert_equal "unparsed", params[:data][:f]
assert_equal [1, "hello", Date.new(1974,7,25)], params[:data][:g]
end


private

Expand Down

0 comments on commit 459559a

Please sign in to comment.