savon 2.11.0 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0909b11e5dac2bc60b3e2e15f8bf614dff389309
4
- data.tar.gz: bbf115546c00147d8703abada768abd1fa5b1abe
3
+ metadata.gz: 5f5d529eeeacffdb613697c1e822ae8f66f48405
4
+ data.tar.gz: 107dbcdf6bf87cffefafeb4216eee8e3b1a8c06f
5
5
  SHA512:
6
- metadata.gz: ae80080f90960964cf8f71f017193bf454fa5027f6607076942c9144c2cc2bfd1d7ea4d8afcc3013e1fc4a1170588b8693a654f6c0a8d714c61777aa5b48fe37
7
- data.tar.gz: f05c5afce92f799b1cf96c019f51e7cb224f6364e4c82677cfdffd9b1a49de149879c0099b0f535b50257fd8e83b188e62e36e9bb6bfb7bf3a6f45aa8236ad7d
6
+ metadata.gz: 49c798231744f066396510436f9eed0a272bb7f189c43395ae54a3bf3a09d012acdd3231fb03cb6d94703d83134fe50f53cfa731f62ec156f05edb2580c45988
7
+ data.tar.gz: 65dde0f62c985730aaf4d77c2414dccd04187979d3173c4419cbb6fd1c2feaa0cc79fac7a67b54b45ef66fa03e862f91b1204c76b3429d806c8ef1f06cd5ff10
data/.travis.yml CHANGED
@@ -1,10 +1,18 @@
1
1
  # https://github.com/travis-ci/travis-ci/wiki/.travis.yml-options
2
2
  language: "ruby"
3
+ sudo: false
4
+ before_install:
5
+ - gem install bundler
3
6
  script: "bundle exec rake --trace"
4
7
  rvm:
5
- - 2.0
6
- - 2.1
7
- - 2.2
8
- - jruby
8
+ - 2.2.4
9
+ - 2.3.0
10
+ - 2.4.1
11
+ - jruby-9.1.15.0
12
+ - rbx-2
13
+ matrix:
14
+ allow_failures:
15
+ - rvm: rbx-2
16
+ fast_finish: true
9
17
  notifications:
10
18
  irc: "irc.freenode.org#savon"
data/CHANGELOG.md CHANGED
@@ -1,3 +1,28 @@
1
+ # 2.12.0 (2018-01-16)
2
+
3
+ * Drop support for ruby 2.1 and below.
4
+ * Fix: [#822](https://github.com/savonrb/savon/pull/822) Raise correct error when SOAP envelope only contains a string
5
+ * Fix: [#833](https://github.com/savonrb/savon/pull/833) Fixes boolean handling regression introduced in 2.11.2
6
+ * Feature: [#794](https://github.com/savonrb/savon/pull/794), add global option ssl_ciphers.
7
+ * Feature: [#753](https://github.com/savonrb/savon/pull/753) Add headers configuration to WSDLRequest#build
8
+ * Feature: [#812](https://github.com/savonrb/savon/pull/812) Allow `proxy` option to be `nil`.
9
+ * Feature: [#838](https://github.com/savonrb/savon/pull/838) Added ssl_ca_path and ssl_cert_store to globals
10
+ * Feature: [#794](https://github.com/savonrb/savon/pull/794) Add global option ssl_ciphers
11
+
12
+
13
+ # 2.11.2 (2017-08-03)
14
+ * Fix: [#676](https://github.com/savonrb/savon/pull/676) Fixes handling of `content!` and `attributes!`
15
+ * Fix: [#800](https://github.com/savonrb/savon/pull/800) Fix exception calling `SOAPFault#to_s` when http.body is empty
16
+ * Fix: [#757](https://github.com/savonrb/savon/pull/757) Logging: Use filter without automatic pretty printing
17
+ * Fix: [#771](https://github.com/savonrb/savon/pull/771) Restore support for cookies when using custom headers
18
+ * Feature: [#744](https://github.com/savonrb/savon/pull/744) Add support for rpc encoded wsdl
19
+ * Feature: [#742](https://github.com/savonrb/savon/pull/742) Add support for local request headers
20
+ * Feature: [#704](https://github.com/savonrb/savon/pull/704) Add possibility to pass attribute delete_namespace_attributes to Nori
21
+
22
+ # 2.11.1 (2015-05-27)
23
+
24
+ * Replace dependency on [uuid](https://rubygems.org/gems/uuid), using SecureRandom.uuid instead.
25
+
1
26
  # 2.11.0 (2015-03-31)
2
27
 
3
28
  * Formally drop support for 1.8.7.
data/Gemfile CHANGED
@@ -1,19 +1,13 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
- gem "httpclient", "~> 2.3.4"
4
+ gem "httpclient", "~> 2.7.1"
5
5
 
6
6
  gem "simplecov", :require => false
7
7
  gem "coveralls", :require => false
8
- gem "uuid"
9
8
 
10
9
  platform :rbx do
11
- gem 'json'
12
10
  gem 'racc'
13
11
  gem 'rubysl'
14
12
  gem 'rubinius-coverage'
15
13
  end
16
-
17
- platform :jruby do
18
- gem 'json'
19
- end
data/README.md CHANGED
@@ -5,10 +5,10 @@ Heavy metal SOAP client
5
5
  [Documentation](http://savonrb.com) | [RDoc](http://rubydoc.info/gems/savon) |
6
6
  [Mailing list](https://groups.google.com/forum/#!forum/savonrb) | [Twitter](http://twitter.com/savonrb)
7
7
 
8
- [![Build Status](https://secure.travis-ci.org/savonrb/savon.png?branch=master)](http://travis-ci.org/savonrb/savon)
9
- [![Gem Version](https://badge.fury.io/rb/savon.png)](http://badge.fury.io/rb/savon)
10
- [![Code Climate](https://codeclimate.com/github/savonrb/savon.png)](https://codeclimate.com/github/savonrb/savon)
11
- [![Coverage Status](https://coveralls.io/repos/savonrb/savon/badge.png?branch=version2)](https://coveralls.io/r/savonrb/savon)
8
+ [![Build Status](https://secure.travis-ci.org/savonrb/savon.svg?branch=master)](http://travis-ci.org/savonrb/savon)
9
+ [![Gem Version](https://badge.fury.io/rb/savon.svg)](http://badge.fury.io/rb/savon)
10
+ [![Code Climate](https://codeclimate.com/github/savonrb/savon.svg)](https://codeclimate.com/github/savonrb/savon)
11
+ [![Coverage Status](https://coveralls.io/repos/savonrb/savon/badge.svg?branch=version2)](https://coveralls.io/r/savonrb/savon)
12
12
 
13
13
 
14
14
  ## Version 2
@@ -22,7 +22,7 @@ $ gem install savon
22
22
  or add it to your Gemfile like this:
23
23
 
24
24
  ```
25
- gem 'savon', '~> 2.10.0'
25
+ gem 'savon', '~> 2.12.0'
26
26
  ```
27
27
 
28
28
  ## Usage example
@@ -46,6 +46,19 @@ response.body
46
46
  For more examples, you should check out the
47
47
  [integration tests](https://github.com/savonrb/savon/tree/version2/spec/integration).
48
48
 
49
+ ## Ruby version support
50
+ * 2.12.x - MRI 2.2, 2.3, 2.4
51
+ * 2.11.x - MRI 2.0, 2.1, 2.2, and 2.3
52
+
53
+ If you are running MRI 1.8.7, try the 2.6.x branch.
54
+
55
+ ## Running tests
56
+
57
+ ```bash
58
+ $ bundle install
59
+ $ bundle exec rspec
60
+ ```
61
+
49
62
  ## FAQ
50
63
 
51
64
  * URI::InvalidURIError -- if you see this error, then it is likely that the http client you are using cannot parse the URI for your WSDL. Try `gem install httpclient` or add it to your `Gemfile`.
data/lib/savon/builder.rb CHANGED
@@ -36,18 +36,18 @@ module Savon
36
36
  end
37
37
 
38
38
  def build_document
39
- xml = tag(builder, :Envelope, namespaces_with_globals) do |xml|
39
+ xml_result = tag(builder, :Envelope, namespaces_with_globals) do |xml|
40
40
  tag(xml, :Header, header_attributes) { xml << header.to_s } unless header.empty?
41
41
  if @globals[:no_message_tag]
42
42
  tag(xml, :Body, body_attributes) { xml << message.to_s }
43
43
  else
44
- tag(xml, :Body, body_attributes) { xml.tag!(*namespaced_message_tag) { xml << message.to_s } }
44
+ tag(xml, :Body, body_attributes) { xml.tag!(*namespaced_message_tag) { xml << body_message } }
45
45
  end
46
46
  end
47
47
 
48
48
  # if we have a signature sign the document
49
49
  if @signature
50
- @signature.document = xml
50
+ @signature.document = xml_result
51
51
 
52
52
  2.times do
53
53
  @header = nil
@@ -61,10 +61,10 @@ module Savon
61
61
  end
62
62
  end
63
63
 
64
- xml = @signature.document
64
+ xml_result = @signature.document
65
65
  end
66
66
 
67
- xml
67
+ xml_result
68
68
  end
69
69
 
70
70
  def header_attributes
@@ -141,6 +141,7 @@ module Savon
141
141
 
142
142
  def namespaced_message_tag
143
143
  tag_name = message_tag
144
+ return [tag_name] if @wsdl.document? and @wsdl.soap_input(@operation_name.to_sym).is_a?(Hash)
144
145
  if namespace_identifier == nil
145
146
  [tag_name, message_attributes]
146
147
  elsif @used_namespaces[[tag_name.to_s]]
@@ -150,8 +151,25 @@ module Savon
150
151
  end
151
152
  end
152
153
 
154
+ def serialized_message_tag
155
+ [:wsdl, @wsdl.soap_input(@operation_name.to_sym).keys.first, {}]
156
+ end
157
+
158
+ def serialized_messages
159
+ messages = ""
160
+ message_tag = serialized_message_tag[1]
161
+ @wsdl.soap_input(@operation_name.to_sym)[message_tag].each_pair do |message, type|
162
+ break if @locals[:message].nil?
163
+ message_locals = @locals[:message][message.snakecase.to_sym]
164
+ message_content = Message.new(message_tag, namespace_identifier, @types, @used_namespaces, message_locals, :unqualified, @globals[:convert_request_keys_to], @globals[:unwrap]).to_s
165
+ messages << "<#{message} xsi:type=\"#{type.join(':')}\">#{message_content}</#{message}>"
166
+ end
167
+ messages
168
+ end
169
+
153
170
  def message_tag
154
- message_tag = @locals[:message_tag]
171
+ message_tag = @wsdl.soap_input(@operation_name.to_sym).keys.first if @wsdl.document? and @wsdl.soap_input(@operation_name.to_sym).is_a?(Hash)
172
+ message_tag ||= @locals[:message_tag]
155
173
  message_tag ||= @wsdl.soap_input(@operation_name.to_sym) if @wsdl.document?
156
174
  message_tag ||= Gyoku.xml_tag(@operation_name, :key_converter => @globals[:convert_request_keys_to])
157
175
 
@@ -162,6 +180,14 @@ module Savon
162
180
  @locals[:attributes] || {}
163
181
  end
164
182
 
183
+ def body_message
184
+ if @wsdl.document? and @wsdl.soap_input(@operation_name.to_sym).is_a?(Hash)
185
+ serialized_messages
186
+ else
187
+ message.to_s
188
+ end
189
+ end
190
+
165
191
  def message
166
192
  element_form_default = @globals[:element_form_default] || @wsdl.element_form_default
167
193
  # TODO: clean this up! [dh, 2012-12-17]
data/lib/savon/client.rb CHANGED
@@ -21,7 +21,7 @@ module Savon
21
21
  build_wsdl_document
22
22
  end
23
23
 
24
- attr_reader :globals
24
+ attr_reader :globals, :wsdl
25
25
 
26
26
  def operations
27
27
  raise_missing_wsdl_error! unless @wsdl.document?
@@ -60,7 +60,6 @@ module Savon
60
60
  @wsdl.document = @globals[:wsdl] if @globals.include? :wsdl
61
61
  @wsdl.endpoint = @globals[:endpoint] if @globals.include? :endpoint
62
62
  @wsdl.namespace = @globals[:namespace] if @globals.include? :namespace
63
- @wsdl.servicename = @globals[:servicename] if @globals.include? :servicename
64
63
  @wsdl.adapter = @globals[:adapter] if @globals.include? :adapter
65
64
 
66
65
  @wsdl.request = WSDLRequest.new(@globals).build
data/lib/savon/header.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require "akami"
2
2
  require "gyoku"
3
- require "uuid"
3
+ require "securerandom"
4
4
 
5
5
  module Savon
6
6
  class Header
@@ -61,7 +61,7 @@ module Savon
61
61
  convert_to_xml({
62
62
  'wsa:Action' => @locals[:soap_action],
63
63
  'wsa:To' => @globals[:endpoint],
64
- 'wsa:MessageID' => "urn:uuid:#{UUID.new.generate}",
64
+ 'wsa:MessageID' => "urn:uuid:#{SecureRandom.uuid}",
65
65
  attributes!: {
66
66
  'wsa:MessageID' => {
67
67
  "xmlns:wsa" => "http://schemas.xmlsoap.org/ws/2004/08/addressing"
@@ -45,7 +45,7 @@ module Savon
45
45
  end
46
46
 
47
47
  def nokogiri_options
48
- @pretty_print ? { :indent => 2 } : {}
48
+ @pretty_print ? { :indent => 2 } : { :save_with => Nokogiri::XML::Node::SaveOptions::AS_XML }
49
49
  end
50
50
 
51
51
  end
@@ -55,7 +55,7 @@ module Savon
55
55
 
56
56
  def verify_message!
57
57
  return if @expected[:message].eql? :any
58
- unless @expected[:message] === @actual[:message]
58
+ unless equals_except_any(@expected[:message], @actual[:message])
59
59
  expected_message = " with this message: #{@expected[:message].inspect}" if @expected[:message]
60
60
  expected_message ||= " with no message."
61
61
 
@@ -63,9 +63,18 @@ module Savon
63
63
  actual_message ||= " with no message."
64
64
 
65
65
  raise ExpectationError, "Expected a request to the #{@expected[:operation_name].inspect} operation\n#{expected_message}\n" \
66
- "Received a request to the #{@actual[:operation_name].inspect} operation\n#{actual_message}"
66
+ "Received a request to the #{@actual[:operation_name].inspect} operation\n#{actual_message}"
67
67
  end
68
68
  end
69
69
 
70
+ def equals_except_any(msg_expected, msg_real)
71
+ return true if msg_expected === msg_real
72
+ return false if (msg_expected.nil? || msg_real.nil?) # If both are nil has returned true
73
+ msg_expected.each do |key, expected_value|
74
+ next if (expected_value == :any && msg_real.include?(key))
75
+ return false if expected_value != msg_real[key]
76
+ end
77
+ return true
78
+ end
70
79
  end
71
80
  end
@@ -100,7 +100,8 @@ module Savon
100
100
 
101
101
  request = SOAPRequest.new(@globals).build(
102
102
  :soap_action => soap_action,
103
- :cookies => @locals[:cookies]
103
+ :cookies => @locals[:cookies],
104
+ :headers => @locals[:headers]
104
105
  )
105
106
 
106
107
  request.url = endpoint
@@ -126,7 +127,13 @@ module Savon
126
127
  end
127
128
 
128
129
  def endpoint
129
- @globals[:endpoint] || @wsdl.endpoint
130
+ @globals[:endpoint] || @wsdl.endpoint.tap do |url|
131
+ if @globals[:host]
132
+ host_url = URI.parse(@globals[:host])
133
+ url.host = host_url.host
134
+ url.port = host_url.port
135
+ end
136
+ end
130
137
  end
131
138
 
132
139
  def raise_expected_httpi_response!
data/lib/savon/options.rb CHANGED
@@ -73,23 +73,25 @@ module Savon
73
73
  @option_type = :global
74
74
 
75
75
  defaults = {
76
- :encoding => "UTF-8",
77
- :soap_version => 1,
78
- :namespaces => {},
79
- :logger => Logger.new($stdout),
80
- :log => false,
81
- :filters => [],
82
- :pretty_print_xml => false,
83
- :raise_errors => true,
84
- :strip_namespaces => true,
85
- :convert_response_tags_to => lambda { |tag| tag.snakecase.to_sym},
86
- :convert_attributes_to => lambda { |k,v| [k,v] },
87
- :multipart => false,
88
- :adapter => nil,
89
- :use_wsa_headers => false,
90
- :no_message_tag => false,
91
- :follow_redirects => false,
92
- :unwrap => false
76
+ :encoding => "UTF-8",
77
+ :soap_version => 1,
78
+ :namespaces => {},
79
+ :logger => Logger.new($stdout),
80
+ :log => false,
81
+ :filters => [],
82
+ :pretty_print_xml => false,
83
+ :raise_errors => true,
84
+ :strip_namespaces => true,
85
+ :delete_namespace_attributes => false,
86
+ :convert_response_tags_to => lambda { |tag| tag.snakecase.to_sym},
87
+ :convert_attributes_to => lambda { |k,v| [k,v] },
88
+ :multipart => false,
89
+ :adapter => nil,
90
+ :use_wsa_headers => false,
91
+ :no_message_tag => false,
92
+ :follow_redirects => false,
93
+ :unwrap => false,
94
+ :host => nil
93
95
  }
94
96
 
95
97
  options = defaults.merge(options)
@@ -108,6 +110,11 @@ module Savon
108
110
  @options[:wsdl] = wsdl_address
109
111
  end
110
112
 
113
+ # set different host for actions in WSDL
114
+ def host(host)
115
+ @options[:host] = host
116
+ end
117
+
111
118
  # SOAP endpoint.
112
119
  def endpoint(endpoint)
113
120
  @options[:endpoint] = endpoint
@@ -130,7 +137,7 @@ module Savon
130
137
 
131
138
  # Proxy server to use for all requests.
132
139
  def proxy(proxy)
133
- @options[:proxy] = proxy
140
+ @options[:proxy] = proxy unless proxy.nil?
134
141
  end
135
142
 
136
143
  # A Hash of HTTP headers.
@@ -261,6 +268,19 @@ module Savon
261
268
  @options[:ssl_ca_cert] = cert
262
269
  end
263
270
 
271
+ def ssl_ciphers(ciphers)
272
+ @options[:ssl_ciphers] = ciphers
273
+ end
274
+
275
+ # Sets the ca cert path.
276
+ def ssl_ca_cert_path(path)
277
+ @options[:ssl_ca_cert_path] = path
278
+ end
279
+
280
+ # Sets the ssl cert store.
281
+ def ssl_cert_store(store)
282
+ @options[:ssl_cert_store] = store
283
+ end
264
284
 
265
285
  # HTTP basic auth credentials.
266
286
  def basic_auth(*credentials)
@@ -282,6 +302,11 @@ module Savon
282
302
  @options[:strip_namespaces] = strip_namespaces
283
303
  end
284
304
 
305
+ # Instruct Nori whether to delete namespace attributes from XML nodes.
306
+ def delete_namespace_attributes(delete_namespace_attributes)
307
+ @options[:delete_namespace_attributes] = delete_namespace_attributes
308
+ end
309
+
285
310
  # Tell Gyoku how to convert Hash key Symbols to XML tags.
286
311
  # Accepts one of :lower_camelcase, :camelcase, :upcase, or :none.
287
312
  def convert_request_keys_to(converter)
@@ -400,5 +425,9 @@ module Savon
400
425
  def multipart(multipart)
401
426
  @options[:multipart] = multipart
402
427
  end
428
+
429
+ def headers(headers)
430
+ @options[:headers] = headers
431
+ end
403
432
  end
404
433
  end
@@ -2,49 +2,50 @@ require "gyoku"
2
2
 
3
3
  module Savon
4
4
  class QualifiedMessage
5
-
6
5
  def initialize(types, used_namespaces, key_converter)
7
- @types = types
6
+ @types = types
8
7
  @used_namespaces = used_namespaces
9
- @key_converter = key_converter
8
+ @key_converter = key_converter
10
9
  end
11
10
 
12
11
  def to_hash(hash, path)
13
12
  return hash unless hash
14
- return hash.map { |value| to_hash(value, path) } if hash.kind_of?(Array)
15
- return hash.to_s unless hash.kind_of? Hash
16
-
17
- hash.inject({}) do |newhash, (key, value)|
18
- if key == :order!
19
- add_namespaces_to_values(value, path)
20
- newhash.merge(key => value)
13
+ return hash.map { |value| to_hash(value, path) } if hash.is_a?(Array)
14
+ return hash.to_s unless hash.is_a?(Hash)
15
+
16
+ hash.each_with_object({}) do |(key, value), newhash|
17
+ case key
18
+ when :order!
19
+ newhash[key] = add_namespaces_to_values(value, path)
20
+ when :attributes!, :content!
21
+ newhash[key] = to_hash(value, path)
21
22
  else
22
- translated_key = Gyoku.xml_tag(key, :key_converter => @key_converter).to_s
23
- translated_key << "!" if key[-1] == "!"
24
- newpath = path + [translated_key]
25
-
26
- if @used_namespaces[newpath]
27
- newhash.merge(
28
- "#{@used_namespaces[newpath]}:#{translated_key}" =>
29
- to_hash(value, @types[newpath] ? [@types[newpath]] : newpath)
30
- )
23
+ if key.to_s =~ /!$/
24
+ newhash[key] = value
31
25
  else
32
- newhash.merge(translated_key => value)
26
+ translated_key = translate_tag(key)
27
+ newkey = add_namespaces_to_values(key, path).first
28
+ newpath = path + [translated_key]
29
+ newhash[newkey] = to_hash(value, newpath)
33
30
  end
34
31
  end
32
+ newhash
35
33
  end
36
34
  end
37
35
 
38
36
  private
39
37
 
40
- def add_namespaces_to_values(values, path)
41
- values.collect! { |value|
42
- camelcased_value = Gyoku.xml_tag(value, :key_converter => @key_converter)
43
- namespace_path = path + [camelcased_value.to_s]
44
- namespace = @used_namespaces[namespace_path]
45
- "#{namespace.blank? ? '' : namespace + ":"}#{camelcased_value}"
46
- }
38
+ def translate_tag(key)
39
+ Gyoku.xml_tag(key, :key_converter => @key_converter).to_s
47
40
  end
48
41
 
42
+ def add_namespaces_to_values(values, path)
43
+ Array(values).collect do |value|
44
+ translated_value = translate_tag(value)
45
+ namespace_path = path + [translated_value]
46
+ namespace = @used_namespaces[namespace_path]
47
+ namespace.blank? ? value : "#{namespace}:#{translated_value}"
48
+ end
49
+ end
49
50
  end
50
51
  end