pax_global_header00006660000000000000000000000064131046401450014510gustar00rootroot0000000000000052 comment=44befe565b5bc4036721a5f756e68e39ea52624e actionpack-xml_parser-2.0.1/000077500000000000000000000000001310464014500157765ustar00rootroot00000000000000actionpack-xml_parser-2.0.1/.gitignore000066400000000000000000000002241310464014500177640ustar00rootroot00000000000000*.gem *.rbc .bundle .config .yardoc *.lock InstalledFiles _yardoc coverage doc/ lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp actionpack-xml_parser-2.0.1/.travis.yml000066400000000000000000000003411310464014500201050ustar00rootroot00000000000000language: ruby sudo: false rvm: - 2.2.5 - 2.3.1 - ruby-head gemfile: - gemfiles/Gemfile-edge - Gemfile notifications: email: false matrix: fast_finish: true allow_failures: - rvm: ruby-head cache: bundler actionpack-xml_parser-2.0.1/Gemfile000066400000000000000000000000471310464014500172720ustar00rootroot00000000000000source 'https://rubygems.org' gemspec actionpack-xml_parser-2.0.1/LICENSE000066400000000000000000000020621310464014500170030ustar00rootroot00000000000000Copyright (c) 2013 Prem Sichanugrist MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. actionpack-xml_parser-2.0.1/README.md000066400000000000000000000032141310464014500172550ustar00rootroot00000000000000actionpack-xml\_parser ====================== A XML parameters parser for Action Pack (removed from core in Rails 4.0) Installation ------------ Include this gem into your Gemfile: ```ruby gem 'actionpack-xml_parser' ``` Parameters parsing rules ------------------------ The parameters parsing is handled by `ActiveSupport::XMLConverter` so there may be specific features and subtle differences depending on the chosen XML backend. ### Hashes Basically, each node represents a key. With the following XML: ```xml David ``` The resulting parameters will be: ```ruby {"person" => {"name" => "David"}} ``` ### File attachment You can specify the `type` attribute of a node to attach files: ```xml ``` The resulting parameters will include a `StringIO` object with the given content, name and content type set accordingly: ```ruby {"person" => {"avatar" => #}} ``` ### Arrays There are several ways to pass an array. You can either specify multiple nodes with the same name: ```xml
``` The resulting parameters will be: ```ruby {"person" => {"address" => [{"city" => "Chicago"}, {"city" => "Ottawa"}]}} ``` You can also specify the `type` attribute of a node and nest child nodes inside: ```xml
``` will result in: ```ruby {"person" => {"addresses" => [{"city" => "Melbourne"}, {"city" => "Paris"}]}} ``` actionpack-xml_parser-2.0.1/Rakefile000066400000000000000000000003141310464014500174410ustar00rootroot00000000000000#!/usr/bin/env rake require "bundler/gem_tasks" require 'rake/testtask' Rake::TestTask.new do |t| t.libs = ["test"] t.pattern = "test/**/*_test.rb" t.ruby_opts = ['-w'] end task :default => :test actionpack-xml_parser-2.0.1/actionpack-xml_parser.gemspec000066400000000000000000000014651310464014500236370ustar00rootroot00000000000000$:.push File.expand_path("../lib", __FILE__) require "action_pack/xml_parser/version" Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = 'actionpack-xml_parser' s.version = ActionPack::XmlParser::VERSION s.summary = 'XML parameters parser for Action Pack (removed from core in Rails 4.0)' s.required_ruby_version = '>= 2.2.2' s.license = 'MIT' s.author = 'Prem Sichanugrist' s.email = 's@sikac.hu' s.homepage = 'http://www.rubyonrails.org' s.files = Dir['LICENSE', 'README.md', 'lib/**/*'] s.require_path = 'lib' s.extra_rdoc_files = %w( README.md ) s.rdoc_options.concat ['--main', 'README.md'] s.add_dependency('actionpack', '>= 5.0') s.add_dependency('railties', '>= 5.0') s.add_development_dependency('rake') end actionpack-xml_parser-2.0.1/gemfiles/000077500000000000000000000000001310464014500175715ustar00rootroot00000000000000actionpack-xml_parser-2.0.1/gemfiles/Gemfile-edge000066400000000000000000000002451310464014500217670ustar00rootroot00000000000000source 'https://rubygems.org' gemspec path: '..' gem 'actionpack', github: 'rails/rails', branch: 'master' gem 'railties', github: 'rails/rails', branch: 'master' actionpack-xml_parser-2.0.1/lib/000077500000000000000000000000001310464014500165445ustar00rootroot00000000000000actionpack-xml_parser-2.0.1/lib/action_pack/000077500000000000000000000000001310464014500210175ustar00rootroot00000000000000actionpack-xml_parser-2.0.1/lib/action_pack/xml_parser.rb000066400000000000000000000007631310464014500235260ustar00rootroot00000000000000require 'active_support' require 'active_support/core_ext/hash/conversions' require 'action_dispatch' require 'action_dispatch/http/request' require 'action_pack/xml_parser/version' module ActionPack class XmlParser def self.register original_parsers = ActionDispatch::Request.parameter_parsers ActionDispatch::Request.parameter_parsers = original_parsers.merge(Mime[:xml].symbol => self) end def self.call(raw_post) Hash.from_xml(raw_post) || {} end end end actionpack-xml_parser-2.0.1/lib/action_pack/xml_parser/000077500000000000000000000000001310464014500231735ustar00rootroot00000000000000actionpack-xml_parser-2.0.1/lib/action_pack/xml_parser/railtie.rb000066400000000000000000000003451310464014500251530ustar00rootroot00000000000000require 'action_pack/xml_parser' module ActionPack class XmlParser class Railtie < ::Rails::Railtie initializer "actionpack-xml_parser.configure" do ActionPack::XmlParser.register end end end end actionpack-xml_parser-2.0.1/lib/action_pack/xml_parser/version.rb000066400000000000000000000001041310464014500252000ustar00rootroot00000000000000module ActionPack class XmlParser VERSION = "2.0.1" end end actionpack-xml_parser-2.0.1/lib/actionpack-xml_parser.rb000066400000000000000000000001051310464014500233530ustar00rootroot00000000000000require 'action_pack/xml_parser/railtie' if defined?(Rails::Railtie) actionpack-xml_parser-2.0.1/test/000077500000000000000000000000001310464014500167555ustar00rootroot00000000000000actionpack-xml_parser-2.0.1/test/fixtures/000077500000000000000000000000001310464014500206265ustar00rootroot00000000000000actionpack-xml_parser-2.0.1/test/fixtures/500.html000066400000000000000000000000221310464014500220120ustar00rootroot00000000000000500 error fixture actionpack-xml_parser-2.0.1/test/helper.rb000066400000000000000000000046101310464014500205620ustar00rootroot00000000000000require 'bundler/setup' require 'active_support/testing/autorun' require 'action_pack/xml_parser' require 'action_controller' FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures') SharedTestRoutes = ActionDispatch::Routing::RouteSet.new module ActionDispatch module SharedRoutes def before_setup @routes = SharedTestRoutes super end end end class RoutedRackApp attr_reader :routes def initialize(routes, &blk) @routes = routes @stack = ActionDispatch::MiddlewareStack.new(&blk).build(@routes) end def call(env) @stack.call(env) end end class ActionDispatch::IntegrationTest < ActiveSupport::TestCase include ActionDispatch::SharedRoutes ActionPack::XmlParser.register def self.build_app(routes = nil) RoutedRackApp.new(routes || ActionDispatch::Routing::RouteSet.new) do |middleware| middleware.use ActionDispatch::ShowExceptions, ActionDispatch::PublicExceptions.new(FIXTURE_LOAD_PATH) middleware.use Rack::Head yield(middleware) if block_given? end end self.app = build_app # Stub Rails dispatcher so it does not get controller references and # simply return the controller#action as Rack::Body. class StubDispatcher < ::ActionDispatch::Routing::RouteSet::Dispatcher protected def controller_reference(controller_param) controller_param end def dispatch(controller, action, env) [200, {'Content-Type' => 'text/html'}, ["#{controller}##{action}"]] end end def self.stub_controllers old_dispatcher = ActionDispatch::Routing::RouteSet::Dispatcher ActionDispatch::Routing::RouteSet.module_eval { remove_const :Dispatcher } ActionDispatch::Routing::RouteSet.module_eval { const_set :Dispatcher, StubDispatcher } yield ActionDispatch::Routing::RouteSet.new ensure ActionDispatch::Routing::RouteSet.module_eval { remove_const :Dispatcher } ActionDispatch::Routing::RouteSet.module_eval { const_set :Dispatcher, old_dispatcher } end def with_routing(&block) temporary_routes = ActionDispatch::Routing::RouteSet.new old_app, self.class.app = self.class.app, self.class.build_app(temporary_routes) old_routes = SharedTestRoutes silence_warnings { Object.const_set(:SharedTestRoutes, temporary_routes) } yield temporary_routes ensure self.class.app = old_app silence_warnings { Object.const_set(:SharedTestRoutes, old_routes) } end end actionpack-xml_parser-2.0.1/test/webservice_test.rb000066400000000000000000000170551310464014500225070ustar00rootroot00000000000000require 'helper' class WebServiceTest < ActionDispatch::IntegrationTest class TestController < ActionController::Base def assign_parameters if params[:full] render plain: dump_params_keys else render plain: (params.keys - ['controller', 'action']).sort.join(", ") end end def dump_params_keys(hash = params) hash.keys.sort.inject("") do |s, k| value = hash[k] if value.is_a?(Hash) || value.is_a?(ActionController::Parameters) value = "(#{dump_params_keys(value)})" else value = "" end s << ", " unless s.empty? s << "#{k}#{value}" end end end def setup @controller = TestController.new @integration_session = nil end def test_check_parameters with_test_route_set do get "/" assert_equal '', @controller.response.body end end def test_post_xml with_test_route_set do post "/", params: 'content...', headers: {'CONTENT_TYPE' => 'application/xml'} assert_equal 'entry', @controller.response.body assert @controller.params.has_key?(:entry) assert_equal 'content...', @controller.params["entry"]['summary'] assert_equal 'true', @controller.params["entry"]['attributed'] end end def test_put_xml with_test_route_set do put "/", params: 'content...', headers: {'CONTENT_TYPE' => 'application/xml'} assert_equal 'entry', @controller.response.body assert @controller.params.has_key?(:entry) assert_equal 'content...', @controller.params["entry"]['summary'] assert_equal 'true', @controller.params["entry"]['attributed'] end end def test_put_xml_using_a_type_node with_test_route_set do put "/", params: 'content...', headers: {'CONTENT_TYPE' => 'application/xml'} assert_equal 'type', @controller.response.body assert @controller.params.has_key?(:type) assert_equal 'content...', @controller.params["type"]['summary'] assert_equal 'true', @controller.params["type"]['attributed'] end end def test_put_xml_using_a_type_node_and_attribute with_test_route_set do put "/", params: 'false', headers: {'CONTENT_TYPE' => 'application/xml'} assert_equal 'type', @controller.response.body assert @controller.params.has_key?(:type) assert_equal false, @controller.params["type"]['summary'] assert_equal 'true', @controller.params["type"]['attributed'] end end def test_post_xml_using_a_type_node with_test_route_set do post "/", params: 'arial', headers: {'CONTENT_TYPE' => 'application/xml'} assert_equal 'font', @controller.response.body assert @controller.params.has_key?(:font) assert_equal 'arial', @controller.params['font']['type'] assert_equal 'true', @controller.params["font"]['attributed'] end end def test_post_xml_using_a_root_node_named_type with_test_route_set do post "/", params: '33', headers: {'CONTENT_TYPE' => 'application/xml'} assert @controller.params.has_key?(:type) assert_equal 33, @controller.params['type'] end end def test_post_xml_using_an_attributted_node_named_type with_test_route_set do with_params_parsers Mime[:xml].symbol => Proc.new { |data| Hash.from_xml(data)['request'].with_indifferent_access } do post "/", params: 'Arial,123', headers: {'CONTENT_TYPE' => 'application/xml'} assert_equal 'type, z', @controller.response.body assert @controller.params.has_key?(:type) assert_equal 'Arial,12', @controller.params['type'], @controller.params.inspect assert_equal '3', @controller.params['z'], @controller.params.inspect end end end def test_post_xml_using_a_disallowed_type_attribute $stderr = StringIO.new with_test_route_set do post '/', params: 'value', headers: {'CONTENT_TYPE' => 'application/xml'} assert_response 400 post '/', params: 'value', headers: {'CONTENT_TYPE' => 'application/xml'} assert_response 400 end ensure $stderr = STDERR end def test_register_and_use_xml_simple with_test_route_set do with_params_parsers Mime[:xml].symbol => Proc.new { |data| Hash.from_xml(data)['request'].with_indifferent_access } do post "/", params: 'content...SimpleXml', headers: {'CONTENT_TYPE' => 'application/xml'} assert_equal 'summary, title', @controller.response.body assert @controller.params.has_key?(:summary) assert @controller.params.has_key?(:title) assert_equal 'content...', @controller.params["summary"] assert_equal 'SimpleXml', @controller.params["title"] end end end def test_use_xml_ximple_with_empty_request with_test_route_set do assert_nothing_raised { post "/", params: "", headers: {'CONTENT_TYPE' => 'application/xml'} } assert_equal '', @controller.response.body end end def test_dasherized_keys_as_xml with_test_route_set do post "/?full=1", params: "\n...\n", headers: {'CONTENT_TYPE' => 'application/xml'} assert_equal 'action, controller, first_key(sub_key), full', @controller.response.body assert_equal "...", @controller.params[:first_key][:sub_key] end end def test_typecast_as_xml with_test_route_set do xml = <<-XML 15 false true 2005-03-17 2005-03-17T21:41:07Z unparsed 1 hello 1974-07-25 XML post "/", params: xml, headers: {'CONTENT_TYPE' => 'application/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 end def test_entities_unescaped_as_xml_simple with_test_route_set do xml = <<-XML <foo "bar's" & friends> XML post "/", params: xml, headers: {'CONTENT_TYPE' => 'application/xml'} assert_equal %(), @controller.params[:data] end end private def with_params_parsers(parsers = {}) old_session = @integration_session original_parsers = ActionDispatch::Request.parameter_parsers ActionDispatch::Request.parameter_parsers = original_parsers.merge parsers reset! yield ensure ActionDispatch::Request.parameter_parsers = original_parsers @integration_session = old_session end def with_test_route_set with_routing do |set| set.draw do match '/', :to => 'web_service_test/test#assign_parameters', :via => :all end yield end end end actionpack-xml_parser-2.0.1/test/xml_params_parsing_test.rb000066400000000000000000000123471310464014500242360ustar00rootroot00000000000000require 'helper' class XmlParamsParsingTest < ActionDispatch::IntegrationTest class TestController < ActionController::Base class << self attr_accessor :last_request_parameters attr_accessor :last_request end def parse self.class.last_request_parameters = request.request_parameters self.class.last_request = request head :ok end end def teardown TestController.last_request_parameters = nil TestController.last_request = nil end def assert_parses(expected, xml) with_test_routing do post "/parse", params: xml, headers: default_headers assert_response :ok assert_equal(expected, TestController.last_request_parameters) end end test "nils are stripped from collections" do assert_parses( {"hash" => { "person" => []} }, "") assert_parses( {"hash" => { "person" => ['foo']} }, "foo\n") end test "parses hash params" do xml = "David" assert_parses({"person" => {"name" => "David"}}, xml) end test "parses single file" do xml = "David#{::Base64.encode64('ABC')}" person = ActionPack::XmlParser.call(xml) assert_equal "image/jpg", person['person']['avatar'].content_type assert_equal "me.jpg", person['person']['avatar'].original_filename assert_equal "ABC", person['person']['avatar'].read end test "logs error if parsing unsuccessful" do with_test_routing do output = StringIO.new xml = "David#{::Base64.encode64('ABC')}" post "/parse", params: xml, headers: default_headers.merge('action_dispatch.show_exceptions' => true, 'action_dispatch.logger' => ActiveSupport::Logger.new(output)) assert_response :bad_request output.rewind && err = output.read assert err =~ /Error occurred while parsing request parameters/ end end test "occurring a parse error if parsing unsuccessful" do with_test_routing do begin $stderr = StringIO.new # suppress the log xml = "David" exception = assert_raise(ActionDispatch::ParamsParser::ParseError) { post "/parse", xml, default_headers.merge('action_dispatch.show_exceptions' => false) } assert_equal REXML::ParseException, exception.original_exception.class assert_equal exception.original_exception.message, exception.message ensure $stderr = STDERR end end end test "parses multiple files" do xml = <<-end_body David #{::Base64.encode64('ABC')} #{::Base64.encode64('DEF')} end_body with_test_routing do post "/parse", params: xml, headers: default_headers assert_response :ok end person = TestController.last_request_parameters 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 assert_equal "image/gif", person['person']['avatars']['avatar'].last.content_type assert_equal "you.gif", person['person']['avatars']['avatar'].last.original_filename assert_equal "DEF", person['person']['avatars']['avatar'].last.read end test "rewinds body if it implements rewind" do xml = "Marie" with_test_routing do post "/parse", params: xml, headers: default_headers assert_equal TestController.last_request.body.read, xml end end private def with_test_routing with_routing do |set| set.draw do post 'parse', to: 'xml_params_parsing_test/test#parse' end yield end end def default_headers {'CONTENT_TYPE' => 'application/xml'} end end class RootLessXmlParamsParsingTest < ActionDispatch::IntegrationTest class TestController < ActionController::Base wrap_parameters :person, :format => :xml class << self attr_accessor :last_request_parameters end def parse self.class.last_request_parameters = request.request_parameters head :ok end end def teardown TestController.last_request_parameters = nil end test "parses hash params" do with_test_routing do xml = "David" post "/parse", params: xml, headers: {'CONTENT_TYPE' => 'application/xml'} assert_response :ok assert_equal({"name" => "David", "person" => {"name" => "David"}}, TestController.last_request_parameters) end end private def with_test_routing with_routing do |set| set.draw do post 'parse', to: 'root_less_xml_params__parsing_test/test#parse' end yield end end end