savon 2.6.0 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 23a1918c1f7d0fca14320681a197cabb6205124a
4
- data.tar.gz: f13e43f5bfde4dce97dd41d676bdecacc3419ffd
3
+ metadata.gz: 3c74bd36381fb8c14d72206e9465e7fa41f91dd8
4
+ data.tar.gz: 1941c3fbe15e58c3f8d4c9a92b057ded090d05e6
5
5
  SHA512:
6
- metadata.gz: 3c00d74d18d3e0b02b5fc2d4981e869692abeb88e7eda80124a9048d472a733e6f128084d512edb98f91cb2ba2bb49f03c4942aaab69cc0154cec9a938b92ce6
7
- data.tar.gz: 8feec6b9dd88fbb4727ae3dce531b75614e1304531df1190b79ba12d129f5d1deb299f81c7d5c6ca275b347062a027bc9ed4e570974334efea796732f3c4e3b8
6
+ metadata.gz: 0db7bf447424f25266cdb79a814e37f0a0260e79d92baaeff979d044df16f0f5c759457a0fdeec4cc16428f4527e596b579a2b1dccdf446fd01cde900d5003a1
7
+ data.tar.gz: 64421f06d8ae1482aa283b455b572ac40ca0e37e30a1da4bdd41efc146074af2c473e6538f5fbafbfecd525131fefe432fc2655733019de18af0fb02ac966b4e
@@ -1,3 +1,12 @@
1
+ # 2.7.0 (2014-09-23)
2
+
3
+ * Feature: Signing requests. Added wsse_signature.
4
+ ```ruby
5
+ client = Savon.client(wsdl: 'http://service.example.com?wsdl') do
6
+ wsse_signature Akami::WSSE::Signature.new(Akami::WSSE::Certs.new(:cert_file => 'c.pem', :private_key_file => 'p.pem'))
7
+ end
8
+ ```
9
+
1
10
  # 2.5.0 (2014-05-03)
2
11
 
3
12
  * Feature: [#573](https://github.com/savonrb/savon/pull/573) Add an `all_operations` method to `Savon::Model` that automatically adds all available operations to the model.
data/README.md CHANGED
@@ -46,6 +46,10 @@ 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
+ ## FAQ
50
+
51
+ * 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`.
52
+ - See https://github.com/savonrb/savon/issues/488 for more info
49
53
 
50
54
  ## Give back
51
55
 
@@ -22,9 +22,10 @@ module Savon
22
22
  def initialize(operation_name, wsdl, globals, locals)
23
23
  @operation_name = operation_name
24
24
 
25
- @wsdl = wsdl
26
- @globals = globals
27
- @locals = locals
25
+ @wsdl = wsdl
26
+ @globals = globals
27
+ @locals = locals
28
+ @signature = @locals[:wsse_signature] || @globals[:wsse_signature]
28
29
 
29
30
  @types = convert_type_definitions_to_hash
30
31
  @used_namespaces = convert_type_namespaces_to_hash
@@ -35,7 +36,7 @@ module Savon
35
36
  end
36
37
 
37
38
  def build_document
38
- tag(builder, :Envelope, namespaces_with_globals) do |xml|
39
+ xml = tag(builder, :Envelope, namespaces_with_globals) do |xml|
39
40
  tag(xml, :Header, header_attributes) { xml << header.to_s } unless header.empty?
40
41
  if @globals[:no_message_tag]
41
42
  tag(xml, :Body, body_attributes) { xml << message.to_s }
@@ -43,6 +44,27 @@ module Savon
43
44
  tag(xml, :Body, body_attributes) { xml.tag!(*namespaced_message_tag) { xml << message.to_s } }
44
45
  end
45
46
  end
47
+
48
+ # if we have a signature sign the document
49
+ if @signature
50
+ @signature.document = xml
51
+
52
+ 2.times do
53
+ @header = nil
54
+ @signature.document = tag(builder, :Envelope, namespaces_with_globals) do |xml|
55
+ tag(xml, :Header, header_attributes) { xml << header.to_s } unless header.empty?
56
+ if @globals[:no_message_tag]
57
+ tag(xml, :Body, body_attributes) { xml << message.to_s }
58
+ else
59
+ tag(xml, :Body, body_attributes) { xml.tag!(*namespaced_message_tag) { xml << message.to_s } }
60
+ end
61
+ end
62
+ end
63
+
64
+ xml = @signature.document
65
+ end
66
+
67
+ xml
46
68
  end
47
69
 
48
70
  def header_attributes
@@ -50,7 +72,7 @@ module Savon
50
72
  end
51
73
 
52
74
  def body_attributes
53
- {}
75
+ @body_attributes ||= @signature.nil? ? {} : @signature.body_attributes
54
76
  end
55
77
 
56
78
  def to_s
@@ -10,6 +10,7 @@ module Savon
10
10
 
11
11
  @wsse_auth = locals[:wsse_auth].nil? ? globals[:wsse_auth] : locals[:wsse_auth]
12
12
  @wsse_timestamp = locals[:wsse_timestamp].nil? ? globals[:wsse_timestamp] : locals[:wsse_timestamp]
13
+ @wsse_signature = locals[:wsse_signature].nil? ? globals[:wsse_signature] : locals[:wsse_signature]
13
14
 
14
15
  @global_header = globals[:soap_header]
15
16
  @local_header = locals[:soap_header]
@@ -21,7 +22,7 @@ module Savon
21
22
  end
22
23
 
23
24
  attr_reader :local_header, :global_header, :gyoku_options,
24
- :wsse_auth, :wsse_timestamp
25
+ :wsse_auth, :wsse_timestamp, :wsse_signature
25
26
 
26
27
  def empty?
27
28
  @header.empty?
@@ -76,6 +77,10 @@ module Savon
76
77
  wsse = Akami.wsse
77
78
  wsse.credentials(*wsse_auth) if wsse_auth
78
79
  wsse.timestamp = wsse_timestamp if wsse_timestamp
80
+ if wsse_signature && wsse_signature.have_document?
81
+ wsse.signature = wsse_signature
82
+ end
83
+
79
84
  wsse
80
85
  end
81
86
 
@@ -35,8 +35,12 @@ module Savon
35
35
  end
36
36
 
37
37
  def apply_filter!(document, filter)
38
- document.xpath("//*[local-name()='#{filter}']").each do |node|
39
- node.content = "***FILTERED***"
38
+ if filter.instance_of? Proc
39
+ filter.call document
40
+ else
41
+ document.xpath("//*[local-name()='#{filter}']").each do |node|
42
+ node.content = "***FILTERED***"
43
+ end
40
44
  end
41
45
  end
42
46
 
@@ -60,6 +60,10 @@ module Savon
60
60
  def wsse_timestamp(timestamp = true)
61
61
  @options[:wsse_timestamp] = timestamp
62
62
  end
63
+
64
+ def wsse_signature(signature)
65
+ @options[:wsse_signature] = signature
66
+ end
63
67
  end
64
68
 
65
69
  class GlobalOptions < Options
@@ -20,6 +20,7 @@ module Savon
20
20
  newhash.merge(key => value)
21
21
  else
22
22
  translated_key = Gyoku.xml_tag(key, :key_converter => @key_converter).to_s
23
+ translated_key << "!" if key[-1] == "!"
23
24
  newpath = path + [translated_key]
24
25
 
25
26
  if @used_namespaces[newpath]
@@ -1,3 +1,3 @@
1
1
  module Savon
2
- VERSION = '2.6.0'
2
+ VERSION = '2.7.0'
3
3
  end
@@ -81,6 +81,43 @@ describe Savon::Builder do
81
81
 
82
82
  expect(builder.to_s).to include("<tns:username>luke</tns:username>")
83
83
  end
84
+
85
+ describe "#wsse_signature" do
86
+ let(:private_key) { "spec/fixtures/ssl/client_key.pem" }
87
+ let(:cert) { "spec/fixtures/ssl/client_cert.pem" }
88
+ let(:signature) { Akami::WSSE::Signature.new(Akami::WSSE::Certs.new(:cert_file => cert, :private_key_file => private_key))}
89
+ let(:globals) { Savon::GlobalOptions.new(wsse_signature: signature) }
90
+
91
+ subject(:signed_message_nn) {Nokogiri::XML(builder.to_s).remove_namespaces!}
92
+ subject(:signed_message) {Nokogiri::XML(builder.to_s)}
93
+
94
+ it "should contain a header" do
95
+ expect(signed_message_nn.xpath('/Envelope/Header').size).to eq(1)
96
+ end
97
+
98
+ it "should contain a wsse:Security" do
99
+ expect(signed_message_nn.xpath('/Envelope/Header/Security').size).to eq(1)
100
+ end
101
+
102
+ it "should have a Body[@wsu:Id]" do
103
+ #must investigate: acts funny in mri ruby
104
+ #expect(signed_message.xpath('//soapenv:Body', soapenv: "http://schemas.xmlsoap.org/soap/envelope/").attribute('ws:Id').value).to include('Body-')
105
+ expect(signed_message_nn.xpath('//Body').attr('Id').value).to include('Body-')
106
+ end
107
+
108
+ it "signature should be valid" do
109
+ certs = Akami::WSSE::Certs.new(:cert_file => cert, :private_key_file => private_key)
110
+ signature_value = signed_message_nn.xpath('//SignatureValue').text
111
+ signed_info_fragment = signed_message.xpath('//default:SignedInfo', default: "http://www.w3.org/2000/09/xmldsig#").to_xml
112
+ data = Nokogiri::XML(signed_info_fragment){|config| config.options = Nokogiri::XML::ParseOptions::NOBLANKS}
113
+ data.root.default_namespace='http://www.w3.org/2000/09/xmldsig#'
114
+
115
+ signed_info = data.canonicalize Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0
116
+
117
+ signature = certs.private_key.sign(OpenSSL::Digest::SHA1.new, signed_info)
118
+ expect(Base64.encode64(signature).gsub("\n", '')).to eq(signature_value)
119
+ end
120
+ end
84
121
  end
85
122
 
86
123
  describe '#body_attributes' do
@@ -26,6 +26,17 @@ describe Savon::LogMessage do
26
26
  expect(message).to include("<password>***FILTERED***</password>")
27
27
  end
28
28
 
29
+ it "properly applies Proc filter" do
30
+ filter = Proc.new do |document|
31
+ document.xpath('//password').each do |node|
32
+ node.content = "FILTERED"
33
+ end
34
+ end
35
+
36
+ message = log_message("<root><password>secret</password></root>", [filter], false).to_s
37
+ expect(message).to include("<password>FILTERED</password>")
38
+ end
39
+
29
40
  def log_message(*args)
30
41
  Savon::LogMessage.new(*args)
31
42
  end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ module Savon
4
+ describe QualifiedMessage, "#to_hash" do
5
+
6
+ context "if a key ends with !" do
7
+ it "restores the ! in a key" do
8
+ used_namespaces = {}
9
+ key_converter = :camelcase
10
+ types = {}
11
+
12
+ message = described_class.new(types, used_namespaces, key_converter)
13
+ resulting_hash = message.to_hash({:Metal! => "<Nice/>"}, ["Rock"])
14
+
15
+ expect(resulting_hash).to eq({"Metal!" => "<Nice/>"})
16
+ end
17
+ end
18
+
19
+ end
20
+ end
metadata CHANGED
@@ -1,139 +1,139 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: savon
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.0
4
+ version: 2.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Harrington
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-26 00:00:00.000000000 Z
11
+ date: 2014-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nori
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: 2.4.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 2.4.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: httpi
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: 2.2.3
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 2.2.3
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: wasabi
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: 3.3.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 3.3.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: akami
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: 1.2.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 1.2.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: gyoku
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ~>
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
75
  version: 1.1.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ~>
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 1.1.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: uuid
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ~>
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
89
  version: 2.3.7
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ~>
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: 2.3.7
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: builder
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - '>='
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
103
  version: 2.1.2
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '>='
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: 2.1.2
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: nokogiri
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - '>='
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
117
  version: 1.4.0
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - '>='
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: 1.4.0
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rack
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - '>='
129
+ - - ">="
130
130
  - !ruby/object:Gem::Version
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - '>='
136
+ - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  - !ruby/object:Gem::Dependency
@@ -154,56 +154,56 @@ dependencies:
154
154
  name: rake
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
- - - ~>
157
+ - - "~>"
158
158
  - !ruby/object:Gem::Version
159
159
  version: '10.1'
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
- - - ~>
164
+ - - "~>"
165
165
  - !ruby/object:Gem::Version
166
166
  version: '10.1'
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: rspec
169
169
  requirement: !ruby/object:Gem::Requirement
170
170
  requirements:
171
- - - ~>
171
+ - - "~>"
172
172
  - !ruby/object:Gem::Version
173
173
  version: '2.14'
174
174
  type: :development
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
- - - ~>
178
+ - - "~>"
179
179
  - !ruby/object:Gem::Version
180
180
  version: '2.14'
181
181
  - !ruby/object:Gem::Dependency
182
182
  name: mocha
183
183
  requirement: !ruby/object:Gem::Requirement
184
184
  requirements:
185
- - - ~>
185
+ - - "~>"
186
186
  - !ruby/object:Gem::Version
187
187
  version: '0.14'
188
188
  type: :development
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
- - - ~>
192
+ - - "~>"
193
193
  - !ruby/object:Gem::Version
194
194
  version: '0.14'
195
195
  - !ruby/object:Gem::Dependency
196
196
  name: json
197
197
  requirement: !ruby/object:Gem::Requirement
198
198
  requirements:
199
- - - ~>
199
+ - - "~>"
200
200
  - !ruby/object:Gem::Version
201
201
  version: '1.7'
202
202
  type: :development
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
- - - ~>
206
+ - - "~>"
207
207
  - !ruby/object:Gem::Version
208
208
  version: '1.7'
209
209
  description: Heavy metal SOAP client
@@ -212,9 +212,9 @@ executables: []
212
212
  extensions: []
213
213
  extra_rdoc_files: []
214
214
  files:
215
- - .gitignore
216
- - .travis.yml
217
- - .yardopts
215
+ - ".gitignore"
216
+ - ".travis.yml"
217
+ - ".yardopts"
218
218
  - CHANGELOG.md
219
219
  - CONTRIBUTING.md
220
220
  - Gemfile
@@ -291,6 +291,7 @@ files:
291
291
  - spec/savon/observers_spec.rb
292
292
  - spec/savon/operation_spec.rb
293
293
  - spec/savon/options_spec.rb
294
+ - spec/savon/qualified_message_spec.rb
294
295
  - spec/savon/request_spec.rb
295
296
  - spec/savon/response_spec.rb
296
297
  - spec/savon/soap_fault_spec.rb
@@ -310,17 +311,17 @@ require_paths:
310
311
  - lib
311
312
  required_ruby_version: !ruby/object:Gem::Requirement
312
313
  requirements:
313
- - - '>='
314
+ - - ">="
314
315
  - !ruby/object:Gem::Version
315
316
  version: '0'
316
317
  required_rubygems_version: !ruby/object:Gem::Requirement
317
318
  requirements:
318
- - - '>='
319
+ - - ">="
319
320
  - !ruby/object:Gem::Version
320
321
  version: '0'
321
322
  requirements: []
322
323
  rubyforge_project: savon
323
- rubygems_version: 2.1.11
324
+ rubygems_version: 2.2.2
324
325
  signing_key:
325
326
  specification_version: 4
326
327
  summary: Heavy metal SOAP client