diff --git a/.travis.yml b/.travis.yml index 4c97c19c..f19b93a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ gemfile: - gemfiles/rails_4.0.0.gemfile - gemfiles/rails_4.1.0.gemfile - gemfiles/rails_4.2.0.gemfile - - gemfiles/rails_5.0.0.gemfile + - gemfiles/rails_5.0.3.gemfile rvm: - 2.3.0 before_install: diff --git a/Appraisals b/Appraisals index 3da841e6..e5879b0b 100644 --- a/Appraisals +++ b/Appraisals @@ -14,6 +14,6 @@ appraise "rails-4.2.0" do end -appraise "rails-5.0.0" do - gem "rails", "5.0.0" +appraise "rails-5.0.3" do + gem "rails", "5.0.3" end diff --git a/README.md b/README.md index dc6c4bd9..bea85bfb 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,13 @@ class RumbasController < ApplicationController render :soap => params[:value].to_s end + soap_action 'single_string_response', + args: { a: :string } + return: :string + def single_string_response + render soap: params[:a].to_s, wrap_response: false + end + soap_action "concat", :args => { :a => :string, :b => :string }, :return => :string @@ -254,6 +261,7 @@ Available properties are: * **namespace**: SOAP namespace to use. Default is `urn:WashOut`. * **snakecase_input**: Determines if WashOut should modify parameters keys to snakecase. Default is `false`. * **camelize_wsdl**: Determines if WashOut should camelize types within WSDL and responses. Supports `true` for CamelCase and `:lower` for camelCase. Default is `false`. +* **service_name**: Allows to define a custom name for the SOAP service. By default, the name is set as `service`. ### Camelization diff --git a/app/helpers/wash_out_helper.rb b/app/helpers/wash_out_helper.rb index 6171e885..1275b9c3 100644 --- a/app/helpers/wash_out_helper.rb +++ b/app/helpers/wash_out_helper.rb @@ -10,6 +10,8 @@ def wsdl_data_options(param) end when 'document' { } + else + { } end end @@ -23,10 +25,12 @@ def wsdl_data_attrs(param) end end - def wsdl_data(xml, params) + def wsdl_data(xml, params, wrap_response = true) params.each do |param| next if param.attribute? + return xml.text! param.value.to_s unless wrap_response == true + tag_name = param.name param_options = wsdl_data_options(param) param_options.merge! wsdl_data_attrs(param) diff --git a/app/views/wash_out/document/response.builder b/app/views/wash_out/document/response.builder index 27bde385..8cb14ad6 100644 --- a/app/views/wash_out/document/response.builder +++ b/app/views/wash_out/document/response.builder @@ -4,14 +4,26 @@ xml.tag! "soap:Envelope", "xmlns:soap" => 'http://schemas.xmlsoap.org/soap/envel "xmlns:tns" => @namespace do if !header.nil? xml.tag! "soap:Header" do - xml.tag! "tns:#{@action_spec[:response_tag]}" do - wsdl_data xml, header + if @response_attribute_tags.nil? + xml.tag! "#{@response_tag.nil? ? 'tns:' : @response_tag}#{@action_spec[:response_tag]}" do + wsdl_data xml, header + end + else + xml.tag! "#{@response_tag.nil? ? 'tns:' : @response_tag}#{@action_spec[:response_tag]}", @response_attribute_tags do + wsdl_data xml, header + end end end end xml.tag! "soap:Body" do - xml.tag! "tns:#{@action_spec[:response_tag]}" do - wsdl_data xml, result + if @response_attribute_tags.nil? + xml.tag! "#{@response_tag.nil? ? 'tns:' : @response_tag}#{@action_spec[:response_tag]}" do + wsdl_data xml, result + end + else + xml.tag! "#{@response_tag.nil? ? 'tns:' : @response_tag}#{@action_spec[:response_tag]}", @response_attribute_tags do + wsdl_data xml, result + end end end end diff --git a/app/views/wash_out/document/wsdl.builder b/app/views/wash_out/document/wsdl.builder index 470d0485..b9e65462 100644 --- a/app/views/wash_out/document/wsdl.builder +++ b/app/views/wash_out/document/wsdl.builder @@ -60,7 +60,7 @@ xml.definitions 'xmlns' => 'http://schemas.xmlsoap.org/wsdl/', end end - xml.service :name => "service" do + xml.service :name => @service_name do xml.port :name => "#{@name}_port", :binding => "tns:#{@name}_binding" do xml.tag! "soap:address", :location => WashOut::Router.url(request, @name) end diff --git a/app/views/wash_out/rpc/response.builder b/app/views/wash_out/rpc/response.builder index 0ccde4e1..25c5c521 100644 --- a/app/views/wash_out/rpc/response.builder +++ b/app/views/wash_out/rpc/response.builder @@ -5,14 +5,26 @@ xml.tag! "soap:Envelope", "xmlns:soap" => 'http://schemas.xmlsoap.org/soap/envel "xmlns:tns" => @namespace do if !header.nil? xml.tag! "soap:Header" do - xml.tag! "tns:#{@action_spec[:response_tag]}" do - wsdl_data xml, header + if @response_attribute_tags.nil? + xml.tag! "#{@response_tag.nil? ? 'tns:' : @response_tag}#{@action_spec[:response_tag]}" do + wsdl_data xml, header + end + else + xml.tag! "#{@response_tag.nil? ? 'tns:' : @response_tag}#{@action_spec[:response_tag]}", @response_attribute_tags do + wsdl_data xml, header + end end end end xml.tag! "soap:Body" do - xml.tag! "tns:#{@action_spec[:response_tag]}" do - wsdl_data xml, result + if @response_attribute_tags.nil? + xml.tag! "#{@response_tag.nil? ? 'tns:' : @response_tag}#{@action_spec[:response_tag]}" do + wsdl_data xml, result + end + else + xml.tag! "#{@response_tag.nil? ? 'tns:' : @response_tag}#{@action_spec[:response_tag]}", @response_attribute_tags do + wsdl_data xml, result + end end end end diff --git a/app/views/wash_out/rpc/wsdl.builder b/app/views/wash_out/rpc/wsdl.builder index 3b9da68f..4ae19306 100644 --- a/app/views/wash_out/rpc/wsdl.builder +++ b/app/views/wash_out/rpc/wsdl.builder @@ -60,7 +60,7 @@ xml.definitions 'xmlns' => 'http://schemas.xmlsoap.org/wsdl/', end end - xml.service :name => "service" do + xml.service :name => @service_name do xml.port :name => "#{@name}_port", :binding => "tns:#{@name}_binding" do xml.tag! "soap:address", :location => WashOut::Router.url(request, @name) end diff --git a/gemfiles/rails_3.2.13.gemfile b/gemfiles/rails_3.2.13.gemfile deleted file mode 100644 index 30a7d846..00000000 --- a/gemfiles/rails_3.2.13.gemfile +++ /dev/null @@ -1,21 +0,0 @@ -# This file was generated by Appraisal - -source "http://rubygems.org" - -gem "wasabi" -gem "savon", ">= 2.0.0" -gem "httpi" -gem "rspec-rails" -gem "guard" -gem "guard-rspec" -gem "rb-fsevent" -gem "appraisal" -gem "tzinfo" -gem "pry" -gem "simplecov" -gem "simplecov-summary" -gem "rails", "3.2.13" -gem "test-unit" -gem "listen", "< 3.1.0" - -gemspec :path => "../" diff --git a/gemfiles/rails_4.0.0.gemfile b/gemfiles/rails_4.0.0.gemfile index b0be367b..6b08fd7e 100644 --- a/gemfiles/rails_4.0.0.gemfile +++ b/gemfiles/rails_4.0.0.gemfile @@ -17,4 +17,4 @@ gem "simplecov-summary" gem "rails", "4.0.0" gem "listen", "< 3.1.0" -gemspec :path => "../" +gemspec path: "../" diff --git a/gemfiles/rails_4.1.0.gemfile b/gemfiles/rails_4.1.0.gemfile index 2ab74511..90819202 100644 --- a/gemfiles/rails_4.1.0.gemfile +++ b/gemfiles/rails_4.1.0.gemfile @@ -17,4 +17,4 @@ gem "simplecov-summary" gem "rails", "4.1.0" gem "listen", "< 3.1.0" -gemspec :path => "../" +gemspec path: "../" diff --git a/gemfiles/rails_4.2.0.gemfile b/gemfiles/rails_4.2.0.gemfile index 4b012b6f..0fb79ec6 100644 --- a/gemfiles/rails_4.2.0.gemfile +++ b/gemfiles/rails_4.2.0.gemfile @@ -17,4 +17,4 @@ gem "simplecov-summary" gem "rails", "4.2.0" gem "listen", "< 3.1.0" -gemspec :path => "../" +gemspec path: "../" diff --git a/gemfiles/rails_5.0.0.beta2.gemfile b/gemfiles/rails_5.0.0.beta2.gemfile deleted file mode 100644 index 11362b1f..00000000 --- a/gemfiles/rails_5.0.0.beta2.gemfile +++ /dev/null @@ -1,19 +0,0 @@ -# This file was generated by Appraisal - -source "http://rubygems.org" - -gem "wasabi" -gem "savon", ">= 2.0.0" -gem "httpi" -gem "rspec-rails" -gem "guard" -gem "guard-rspec" -gem "rb-fsevent" -gem "appraisal" -gem "tzinfo" -gem "pry" -gem "simplecov" -gem "simplecov-summary" -gem "rails", "5.0.0.beta2" - -gemspec :path => "../" diff --git a/gemfiles/rails_5.0.0.gemfile b/gemfiles/rails_5.0.3.gemfile similarity index 85% rename from gemfiles/rails_5.0.0.gemfile rename to gemfiles/rails_5.0.3.gemfile index fa96fd53..69aec8d0 100644 --- a/gemfiles/rails_5.0.0.gemfile +++ b/gemfiles/rails_5.0.3.gemfile @@ -14,6 +14,6 @@ gem "tzinfo" gem "pry" gem "simplecov" gem "simplecov-summary" -gem "rails", "5.0.0" +gem "rails", "5.0.3" -gemspec :path => "../" +gemspec path: "../" diff --git a/lib/wash_out/dispatcher.rb b/lib/wash_out/dispatcher.rb index df5550f8..1ffc68d1 100644 --- a/lib/wash_out/dispatcher.rb +++ b/lib/wash_out/dispatcher.rb @@ -72,9 +72,12 @@ def _load_params(spec, xml_data) # This action generates the WSDL for defined SOAP methods. def _generate_wsdl - @map = self.class.soap_actions - @namespace = soap_config.namespace - @name = controller_path + @map = self.class.soap_actions + @namespace = soap_config.namespace + @response_tag = soap_config.response_tag + @response_attribute_tags = soap_config.response_attribute_tags + @name = controller_path + @service_name = soap_config.service_name render :template => "wash_out/#{soap_config.wsdl_style}/wsdl", :layout => false, :content_type => 'text/xml' @@ -82,9 +85,11 @@ def _generate_wsdl # Render a SOAP response. def _render_soap(result, options) - @namespace = soap_config.namespace - @operation = soap_action = request.env['wash_out.soap_action'] - @action_spec = self.class.soap_actions[soap_action] + @namespace = soap_config.namespace + @response_tag = soap_config.response_tag + @response_attribute_tags = soap_config.response_attribute_tags + @operation = soap_action = request.env['wash_out.soap_action'] + @action_spec = self.class.soap_actions[soap_action] result = { 'value' => result } unless result.is_a? Hash result = HashWithIndifferentAccess.new(result) @@ -137,12 +142,15 @@ def _render_soap(result, options) header = HashWithIndifferentAccess.new(header) end + wrap_response = options.fetch :wrap_response, true + render :template => "wash_out/#{soap_config.wsdl_style}/response", :layout => false, :locals => { :header => header.present? ? inject.call(header, @action_spec[:header_out]) : nil, - :result => inject.call(result, @action_spec[:out]) + :result => inject.call(result, @action_spec[:out]), + :wrap_response => wrap_response }, :content_type => 'text/xml' end diff --git a/lib/wash_out/soap.rb b/lib/wash_out/soap.rb index ec5e25d9..96bf7888 100644 --- a/lib/wash_out/soap.rb +++ b/lib/wash_out/soap.rb @@ -33,7 +33,7 @@ def soap_action(action, options={}) end - default_response_tag = soap_config.camelize_wsdl ? 'Response' : '_response' + default_response_tag = 'Response' default_response_tag = action+default_response_tag diff --git a/lib/wash_out/soap_config.rb b/lib/wash_out/soap_config.rb index 438331a3..1836d2d8 100644 --- a/lib/wash_out/soap_config.rb +++ b/lib/wash_out/soap_config.rb @@ -15,6 +15,9 @@ class SoapConfig wsse_password: nil, wsse_auth_callback: nil, soap_action_routing: true, + service_name: 'service', + response_tag: nil, + response_attribute_tags: nil } attr_reader :config diff --git a/spec/lib/wash_out_spec.rb b/spec/lib/wash_out_spec.rb index 6f1714ba..5bc16ce3 100644 --- a/spec/lib/wash_out_spec.rb +++ b/spec/lib/wash_out_spec.rb @@ -119,6 +119,40 @@ def savon!(method, message={}, &block) end end + describe 'WSDL' do + let :wsdl do + mock_controller + + HTTPI.get('http://app/route/api/wsdl').body + end + + let :xml do + nori.parse wsdl + end + + it "defines a default service name as 'service'" do + service_name = xml[:definitions][:service][:@name] + expect(service_name).to match 'service' + end + end + + describe 'WSDL' do + let :wsdl do + mock_controller service_name: 'CustomServiceName' + + HTTPI.get('http://app/route/api/wsdl').body + end + + let :xml do + nori.parse wsdl + end + + it 'allows to define a custom service name' do + service_name = xml[:definitions][:service][:@name] + expect(service_name).to match 'CustomServiceName' + end + end + describe "Dispatcher" do context "simple actions" do @@ -270,6 +304,18 @@ def funky expect(savon(:funky, :a => 42, :b => 'k')[:funky_response][:value]).to eq '420k' end + + it 'responds with single strings without wraping the response' do + mock_controller do + soap_action 'single_string', args: { a: :string }, return: :string + def single_string + render soap: params[:a], wrap_response: false + end + end + + response = savon(:single_string, a: 'single string')[:single_string_response] + expect(response).to match 'single string' + end end context "complex actions" do