savon 2.11.1 → 2.15.1
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 +5 -5
- data/CHANGELOG.md +132 -73
- data/README.md +35 -20
- data/lib/savon/block_interface.rb +1 -0
- data/lib/savon/builder.rb +126 -30
- data/lib/savon/client.rb +2 -2
- data/lib/savon/header.rb +2 -6
- data/lib/savon/http_error.rb +4 -4
- data/lib/savon/log_message.rb +2 -1
- data/lib/savon/message.rb +1 -0
- data/lib/savon/mock/expectation.rb +1 -0
- data/lib/savon/mock/spec_helper.rb +1 -0
- data/lib/savon/mock.rb +1 -0
- data/lib/savon/model.rb +4 -3
- data/lib/savon/operation.rb +22 -19
- data/lib/savon/options.rb +98 -19
- data/lib/savon/qualified_message.rb +29 -27
- data/lib/savon/request.rb +22 -6
- data/lib/savon/request_logger.rb +8 -2
- data/lib/savon/response.rb +58 -10
- data/lib/savon/soap_fault.rb +3 -4
- data/lib/savon/string_utils.rb +17 -0
- data/lib/savon/version.rb +2 -1
- data/lib/savon.rb +2 -0
- metadata +80 -100
- data/.gitignore +0 -14
- data/.travis.yml +0 -15
- data/.yardopts +0 -6
- data/CONTRIBUTING.md +0 -46
- data/Gemfile +0 -18
- data/donate.png +0 -0
- data/lib/savon/core_ext/string.rb +0 -29
- data/savon.gemspec +0 -46
- data/spec/fixtures/gzip/message.gz +0 -0
- data/spec/fixtures/response/another_soap_fault.xml +0 -14
- data/spec/fixtures/response/authentication.xml +0 -14
- data/spec/fixtures/response/f5.xml +0 -39
- data/spec/fixtures/response/header.xml +0 -13
- data/spec/fixtures/response/list.xml +0 -18
- data/spec/fixtures/response/multi_ref.xml +0 -39
- data/spec/fixtures/response/soap_fault.xml +0 -8
- data/spec/fixtures/response/soap_fault12.xml +0 -18
- data/spec/fixtures/response/soap_fault_funky.xml +0 -8
- data/spec/fixtures/response/taxcloud.xml +0 -1
- data/spec/fixtures/ssl/client_cert.pem +0 -16
- data/spec/fixtures/ssl/client_encrypted_key.pem +0 -30
- data/spec/fixtures/ssl/client_encrypted_key_cert.pem +0 -24
- data/spec/fixtures/ssl/client_key.pem +0 -15
- data/spec/fixtures/wsdl/authentication.xml +0 -63
- data/spec/fixtures/wsdl/betfair.xml +0 -2981
- data/spec/fixtures/wsdl/edialog.xml +0 -15416
- data/spec/fixtures/wsdl/interhome.xml +0 -2137
- data/spec/fixtures/wsdl/lower_camel.xml +0 -52
- data/spec/fixtures/wsdl/multiple_namespaces.xml +0 -92
- data/spec/fixtures/wsdl/multiple_types.xml +0 -60
- data/spec/fixtures/wsdl/no_message_tag.xml +0 -1267
- data/spec/fixtures/wsdl/taxcloud.xml +0 -934
- data/spec/fixtures/wsdl/team_software.xml +0 -1
- data/spec/fixtures/wsdl/vies.xml +0 -176
- data/spec/fixtures/wsdl/wasmuth.xml +0 -153
- data/spec/integration/centra_spec.rb +0 -66
- data/spec/integration/email_example_spec.rb +0 -32
- data/spec/integration/random_quote_spec.rb +0 -23
- data/spec/integration/ratp_example_spec.rb +0 -28
- data/spec/integration/stockquote_example_spec.rb +0 -28
- data/spec/integration/support/application.rb +0 -82
- data/spec/integration/support/server.rb +0 -84
- data/spec/integration/temperature_example_spec.rb +0 -46
- data/spec/integration/zipcode_example_spec.rb +0 -42
- data/spec/savon/builder_spec.rb +0 -137
- data/spec/savon/client_spec.rb +0 -271
- data/spec/savon/core_ext/string_spec.rb +0 -37
- data/spec/savon/features/message_tag_spec.rb +0 -61
- data/spec/savon/http_error_spec.rb +0 -49
- data/spec/savon/log_message_spec.rb +0 -44
- data/spec/savon/message_spec.rb +0 -70
- data/spec/savon/mock_spec.rb +0 -174
- data/spec/savon/model_spec.rb +0 -182
- data/spec/savon/observers_spec.rb +0 -92
- data/spec/savon/operation_spec.rb +0 -230
- data/spec/savon/options_spec.rb +0 -1064
- data/spec/savon/qualified_message_spec.rb +0 -20
- data/spec/savon/request_logger_spec.rb +0 -37
- data/spec/savon/request_spec.rb +0 -496
- data/spec/savon/response_spec.rb +0 -270
- data/spec/savon/soap_fault_spec.rb +0 -131
- data/spec/spec_helper.rb +0 -30
- data/spec/support/adapters.rb +0 -48
- data/spec/support/endpoint.rb +0 -25
- data/spec/support/fixture.rb +0 -39
- data/spec/support/integration.rb +0 -9
- data/spec/support/stdout.rb +0 -25
data/README.md
CHANGED
@@ -2,18 +2,18 @@
|
|
2
2
|
|
3
3
|
Heavy metal SOAP client
|
4
4
|
|
5
|
-
[Documentation](
|
5
|
+
[Documentation](https://www.rubydoc.info/gems/savon/) | [Support](https://stackoverflow.com/questions/tagged/savon) |
|
6
6
|
[Mailing list](https://groups.google.com/forum/#!forum/savonrb) | [Twitter](http://twitter.com/savonrb)
|
7
7
|
|
8
|
-
[](https://github.com/savonrb/savon/actions/workflows/ci.yml)
|
9
|
+
[](http://badge.fury.io/rb/savon)
|
10
|
+
[](https://codeclimate.com/github/savonrb/savon)
|
11
|
+
[](https://coveralls.io/r/savonrb/savon)
|
12
12
|
|
13
13
|
|
14
|
-
##
|
14
|
+
## Installation
|
15
15
|
|
16
|
-
Savon
|
16
|
+
Savon is available through [Rubygems](http://rubygems.org/gems/savon) and can be installed via:
|
17
17
|
|
18
18
|
```
|
19
19
|
$ gem install savon
|
@@ -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.
|
25
|
+
gem 'savon', '~> 2.15.0'
|
26
26
|
```
|
27
27
|
|
28
28
|
## Usage example
|
@@ -33,6 +33,12 @@ require 'savon'
|
|
33
33
|
# create a client for the service
|
34
34
|
client = Savon.client(wsdl: 'http://service.example.com?wsdl')
|
35
35
|
|
36
|
+
# or: create a client with a wsdl provided as a string
|
37
|
+
client = Savon.client do |config|
|
38
|
+
wsdl_content = File.read("/path/to/wsdl")
|
39
|
+
config.wsdl wsdl_content
|
40
|
+
end
|
41
|
+
|
36
42
|
client.operations
|
37
43
|
# => [:find_user, :list_users]
|
38
44
|
|
@@ -46,24 +52,33 @@ response.body
|
|
46
52
|
For more examples, you should check out the
|
47
53
|
[integration tests](https://github.com/savonrb/savon/tree/version2/spec/integration).
|
48
54
|
|
49
|
-
##
|
55
|
+
## Ruby version support
|
50
56
|
|
51
|
-
|
52
|
-
- See https://github.com/savonrb/savon/issues/488 for more info
|
57
|
+
Every savon release is tested with contemporary supported versions of ruby. Historical compatibility information:
|
53
58
|
|
54
|
-
|
59
|
+
* `main` - same support as Ruby
|
60
|
+
* 2.15.x - MRI 3.0, 3.1, 3.2, 3.3
|
61
|
+
* 2.13.x, 2.14.x - MRI 2.7, 3.0, 3.1
|
62
|
+
* 2.12.x - MRI 2.2, 2.3, 2.4, 2.5
|
63
|
+
* 2.11.x - MRI 2.0, 2.1, 2.2, and 2.3
|
55
64
|
|
56
|
-
If you
|
57
|
-
donating via [Gittip](https://www.gittip.com/tjarratt/) so that I can continue to improve it.
|
65
|
+
If you are running MRI 1.8.7, try a 2.6.x release.
|
58
66
|
|
59
|
-
|
67
|
+
Most changes are not backported to older versions of savon, or unsupported ruby versions.
|
60
68
|
|
69
|
+
## Running tests
|
61
70
|
|
62
|
-
|
71
|
+
```bash
|
72
|
+
$ bundle install
|
73
|
+
$ bundle exec rspec
|
74
|
+
```
|
75
|
+
|
76
|
+
## FAQ
|
77
|
+
|
78
|
+
* 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`.
|
79
|
+
- See https://github.com/savonrb/savon/issues/488 for more info
|
63
80
|
|
64
|
-
Please make sure to [read the documentation](http://savonrb.com/version2/).
|
65
81
|
|
66
|
-
|
67
|
-
feel free to [help out and improve the documentation](https://github.com/savonrb/savonrb.com).
|
82
|
+
## Documentation
|
68
83
|
|
69
|
-
|
84
|
+
Please be sure to [read the documentation](https://www.rubydoc.info/github/savonrb/savon/).
|
data/lib/savon/builder.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "savon/header"
|
2
3
|
require "savon/message"
|
3
4
|
require "nokogiri"
|
@@ -6,6 +7,7 @@ require "gyoku"
|
|
6
7
|
|
7
8
|
module Savon
|
8
9
|
class Builder
|
10
|
+
attr_reader :multipart
|
9
11
|
|
10
12
|
SCHEMA_TYPES = {
|
11
13
|
"xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
|
@@ -36,35 +38,27 @@ module Savon
|
|
36
38
|
end
|
37
39
|
|
38
40
|
def build_document
|
39
|
-
|
40
|
-
tag(xml, :Header, header_attributes) { xml << header.to_s } unless header.empty?
|
41
|
-
if @globals[:no_message_tag]
|
42
|
-
tag(xml, :Body, body_attributes) { xml << message.to_s }
|
43
|
-
else
|
44
|
-
tag(xml, :Body, body_attributes) { xml.tag!(*namespaced_message_tag) { xml << message.to_s } }
|
45
|
-
end
|
46
|
-
end
|
41
|
+
xml_result = build_xml
|
47
42
|
|
48
43
|
# if we have a signature sign the document
|
49
44
|
if @signature
|
50
|
-
@signature.document =
|
45
|
+
@signature.document = xml_result
|
51
46
|
|
52
47
|
2.times do
|
53
48
|
@header = nil
|
54
|
-
@signature.document =
|
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
|
49
|
+
@signature.document = build_xml
|
62
50
|
end
|
63
51
|
|
64
|
-
|
52
|
+
xml_result = @signature.document
|
65
53
|
end
|
66
54
|
|
67
|
-
|
55
|
+
# if there are attachments for the request, we should build a multipart message according to
|
56
|
+
# https://www.w3.org/TR/SOAP-attachments
|
57
|
+
if @locals[:attachments]
|
58
|
+
build_multipart_message(xml_result)
|
59
|
+
else
|
60
|
+
xml_result
|
61
|
+
end
|
68
62
|
end
|
69
63
|
|
70
64
|
def header_attributes
|
@@ -117,15 +111,25 @@ module Savon
|
|
117
111
|
@namespaces ||= begin
|
118
112
|
namespaces = SCHEMA_TYPES.dup
|
119
113
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
114
|
+
# check namespace_identifier
|
115
|
+
namespaces["xmlns#{namespace_identifier.nil? ? '' : ":#{namespace_identifier}"}"] =
|
116
|
+
@globals[:namespace] || @wsdl.namespace
|
117
|
+
|
118
|
+
# check env_namespace
|
119
|
+
namespaces["xmlns#{env_namespace && env_namespace != "" ? ":#{env_namespace}" : ''}"] =
|
120
|
+
SOAP_NAMESPACE[@globals[:soap_version]]
|
121
|
+
|
122
|
+
if @wsdl&.document
|
123
|
+
@wsdl.parser.namespaces.each do |identifier, path|
|
124
|
+
next if identifier == 'xmlns' # Do not include xmlns namespace as this causes issues for some servers (https://github.com/savonrb/savon/issues/986)
|
125
125
|
|
126
|
-
|
127
|
-
|
128
|
-
|
126
|
+
prefixed_identifier = "xmlns:#{identifier}"
|
127
|
+
|
128
|
+
next if namespaces.key?(prefixed_identifier)
|
129
|
+
|
130
|
+
namespaces[prefixed_identifier] = path
|
131
|
+
end
|
132
|
+
end
|
129
133
|
|
130
134
|
namespaces
|
131
135
|
end
|
@@ -141,6 +145,7 @@ module Savon
|
|
141
145
|
|
142
146
|
def namespaced_message_tag
|
143
147
|
tag_name = message_tag
|
148
|
+
return [tag_name] if @wsdl.document? and @wsdl.soap_input(@operation_name.to_sym).is_a?(Hash)
|
144
149
|
if namespace_identifier == nil
|
145
150
|
[tag_name, message_attributes]
|
146
151
|
elsif @used_namespaces[[tag_name.to_s]]
|
@@ -150,18 +155,45 @@ module Savon
|
|
150
155
|
end
|
151
156
|
end
|
152
157
|
|
158
|
+
def serialized_message_tag
|
159
|
+
[:wsdl, @wsdl.soap_input(@operation_name.to_sym).keys.first, {}]
|
160
|
+
end
|
161
|
+
|
162
|
+
def serialized_messages
|
163
|
+
messages = ""
|
164
|
+
message_tag = serialized_message_tag[1]
|
165
|
+
@wsdl.soap_input(@operation_name.to_sym)[message_tag].each_pair do |message, type|
|
166
|
+
break if @locals[:message].nil?
|
167
|
+
message_locals = @locals[:message][StringUtils.snakecase(message).to_sym]
|
168
|
+
message_content = Message.new(message_tag, namespace_identifier, @types, @used_namespaces, message_locals, :unqualified, @globals[:convert_request_keys_to], @globals[:unwrap]).to_s
|
169
|
+
messages += "<#{message} xsi:type=\"#{type.join(':')}\">#{message_content}</#{message}>"
|
170
|
+
end
|
171
|
+
messages
|
172
|
+
end
|
173
|
+
|
153
174
|
def message_tag
|
154
|
-
|
155
|
-
|
175
|
+
wsdl_tag_name = @wsdl.document? && @wsdl.soap_input(@operation_name.to_sym)
|
176
|
+
|
177
|
+
message_tag = wsdl_tag_name.keys.first if wsdl_tag_name.is_a?(Hash)
|
178
|
+
message_tag ||= @locals[:message_tag]
|
179
|
+
message_tag ||= wsdl_tag_name
|
156
180
|
message_tag ||= Gyoku.xml_tag(@operation_name, :key_converter => @globals[:convert_request_keys_to])
|
157
181
|
|
158
|
-
|
182
|
+
message_tag.to_sym
|
159
183
|
end
|
160
184
|
|
161
185
|
def message_attributes
|
162
186
|
@locals[:attributes] || {}
|
163
187
|
end
|
164
188
|
|
189
|
+
def body_message
|
190
|
+
if @wsdl.document? and @wsdl.soap_input(@operation_name.to_sym).is_a?(Hash)
|
191
|
+
serialized_messages
|
192
|
+
else
|
193
|
+
message.to_s
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
165
197
|
def message
|
166
198
|
element_form_default = @globals[:element_form_default] || @wsdl.element_form_default
|
167
199
|
# TODO: clean this up! [dh, 2012-12-17]
|
@@ -201,5 +233,69 @@ module Savon
|
|
201
233
|
end
|
202
234
|
end
|
203
235
|
|
236
|
+
def build_xml
|
237
|
+
tag(builder, :Envelope, namespaces_with_globals) do |xml|
|
238
|
+
tag(xml, :Header, header_attributes) { xml << header.to_s } unless header.empty?
|
239
|
+
tag(xml, :Body, body_attributes) do
|
240
|
+
if @globals[:no_message_tag]
|
241
|
+
xml << message.to_s
|
242
|
+
else
|
243
|
+
xml.tag!(*namespaced_message_tag) { xml << body_message }
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def build_multipart_message(message_xml)
|
250
|
+
multipart_message = init_multipart_message(message_xml)
|
251
|
+
add_attachments_to_multipart_message(multipart_message)
|
252
|
+
|
253
|
+
multipart_message.ready_to_send!
|
254
|
+
|
255
|
+
# the mail.body.encoded algorithm reorders the parts, default order is [ "text/plain", "text/enriched", "text/html" ]
|
256
|
+
# should redefine the sort order, because the soap request xml should be the first
|
257
|
+
multipart_message.body.set_sort_order [ "text/xml" ]
|
258
|
+
|
259
|
+
multipart_message.body.encoded(multipart_message.content_transfer_encoding)
|
260
|
+
end
|
261
|
+
|
262
|
+
def init_multipart_message(message_xml)
|
263
|
+
multipart_message = Mail.new
|
264
|
+
xml_part = Mail::Part.new do
|
265
|
+
content_type 'text/xml'
|
266
|
+
body message_xml
|
267
|
+
# in Content-Type the start parameter is recommended (RFC 2387)
|
268
|
+
content_id '<soap-request-body@soap>'
|
269
|
+
end
|
270
|
+
multipart_message.add_part xml_part
|
271
|
+
|
272
|
+
#request.headers["Content-Type"] = "multipart/related; boundary=\"#{multipart_message.body.boundary}\"; type=\"text/xml\"; start=\"#{xml_part.content_id}\""
|
273
|
+
@multipart = {
|
274
|
+
multipart_boundary: multipart_message.body.boundary,
|
275
|
+
start: xml_part.content_id,
|
276
|
+
}
|
277
|
+
|
278
|
+
multipart_message
|
279
|
+
end
|
280
|
+
|
281
|
+
def add_attachments_to_multipart_message(multipart_message)
|
282
|
+
if @locals[:attachments].is_a? Hash
|
283
|
+
# hash example: { 'att1' => '/path/to/att1', 'att2' => '/path/to/att2' }
|
284
|
+
@locals[:attachments].each do |identifier, attachment|
|
285
|
+
add_attachment_to_multipart_message(multipart_message, attachment, identifier)
|
286
|
+
end
|
287
|
+
elsif @locals[:attachments].is_a? Array
|
288
|
+
# array example: [ '/path/to/att1', '/path/to/att2' ]
|
289
|
+
# array example: [ { filename: 'att1.xml', content: '<x/>' }, { filename: 'att2.xml', content: '<y/>' } ]
|
290
|
+
@locals[:attachments].each do |attachment|
|
291
|
+
add_attachment_to_multipart_message(multipart_message, attachment, attachment.is_a?(String) ? File.basename(attachment) : attachment[:filename])
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
def add_attachment_to_multipart_message(multipart_message, attachment, identifier)
|
297
|
+
multipart_message.add_file attachment.clone
|
298
|
+
multipart_message.parts.last.content_id = multipart_message.parts.last.content_location = identifier.to_s
|
299
|
+
end
|
204
300
|
end
|
205
301
|
end
|
data/lib/savon/client.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "savon/operation"
|
2
3
|
require "savon/request"
|
3
4
|
require "savon/options"
|
@@ -21,7 +22,7 @@ module Savon
|
|
21
22
|
build_wsdl_document
|
22
23
|
end
|
23
24
|
|
24
|
-
attr_reader :globals
|
25
|
+
attr_reader :globals, :wsdl
|
25
26
|
|
26
27
|
def operations
|
27
28
|
raise_missing_wsdl_error! unless @wsdl.document?
|
@@ -60,7 +61,6 @@ module Savon
|
|
60
61
|
@wsdl.document = @globals[:wsdl] if @globals.include? :wsdl
|
61
62
|
@wsdl.endpoint = @globals[:endpoint] if @globals.include? :endpoint
|
62
63
|
@wsdl.namespace = @globals[:namespace] if @globals.include? :namespace
|
63
|
-
@wsdl.servicename = @globals[:servicename] if @globals.include? :servicename
|
64
64
|
@wsdl.adapter = @globals[:adapter] if @globals.include? :adapter
|
65
65
|
|
66
66
|
@wsdl.request = WSDLRequest.new(@globals).build
|
data/lib/savon/header.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "akami"
|
2
3
|
require "gyoku"
|
3
4
|
require "securerandom"
|
@@ -61,12 +62,7 @@ module Savon
|
|
61
62
|
convert_to_xml({
|
62
63
|
'wsa:Action' => @locals[:soap_action],
|
63
64
|
'wsa:To' => @globals[:endpoint],
|
64
|
-
'wsa:MessageID' => "urn:uuid:#{SecureRandom.uuid}"
|
65
|
-
attributes!: {
|
66
|
-
'wsa:MessageID' => {
|
67
|
-
"xmlns:wsa" => "http://schemas.xmlsoap.org/ws/2004/08/addressing"
|
68
|
-
}
|
69
|
-
}
|
65
|
+
'wsa:MessageID' => "urn:uuid:#{SecureRandom.uuid}"
|
70
66
|
})
|
71
67
|
end
|
72
68
|
|
data/lib/savon/http_error.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Savon
|
4
4
|
class HTTPError < Error
|
@@ -14,9 +14,9 @@ module Savon
|
|
14
14
|
attr_reader :http
|
15
15
|
|
16
16
|
def to_s
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
String.new("HTTP error (#{@http.code})").tap do |str_error|
|
18
|
+
str_error << ": #{@http.body}" unless @http.body.empty?
|
19
|
+
end
|
20
20
|
end
|
21
21
|
|
22
22
|
def to_hash
|
data/lib/savon/log_message.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "nokogiri"
|
2
3
|
|
3
4
|
module Savon
|
@@ -45,7 +46,7 @@ module Savon
|
|
45
46
|
end
|
46
47
|
|
47
48
|
def nokogiri_options
|
48
|
-
@pretty_print ? { :indent => 2 } : {}
|
49
|
+
@pretty_print ? { :indent => 2 } : { :save_with => Nokogiri::XML::Node::SaveOptions::AS_XML }
|
49
50
|
end
|
50
51
|
|
51
52
|
end
|
data/lib/savon/message.rb
CHANGED
data/lib/savon/mock.rb
CHANGED
data/lib/savon/model.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Savon
|
2
3
|
module Model
|
3
4
|
|
@@ -28,7 +29,7 @@ module Savon
|
|
28
29
|
# Defines a class-level SOAP operation.
|
29
30
|
def define_class_operation(operation)
|
30
31
|
class_operation_module.module_eval %{
|
31
|
-
def #{operation.to_s
|
32
|
+
def #{StringUtils.snakecase(operation.to_s)}(locals = {})
|
32
33
|
client.call #{operation.inspect}, locals
|
33
34
|
end
|
34
35
|
}
|
@@ -37,8 +38,8 @@ module Savon
|
|
37
38
|
# Defines an instance-level SOAP operation.
|
38
39
|
def define_instance_operation(operation)
|
39
40
|
instance_operation_module.module_eval %{
|
40
|
-
def #{operation.to_s
|
41
|
-
self.class.#{operation.to_s
|
41
|
+
def #{StringUtils.snakecase(operation.to_s)}(locals = {})
|
42
|
+
self.class.#{StringUtils.snakecase(operation.to_s)} locals
|
42
43
|
end
|
43
44
|
}
|
44
45
|
end
|
data/lib/savon/operation.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "savon/options"
|
2
3
|
require "savon/block_interface"
|
3
4
|
require "savon/request"
|
@@ -5,10 +6,16 @@ require "savon/builder"
|
|
5
6
|
require "savon/response"
|
6
7
|
require "savon/request_logger"
|
7
8
|
require "savon/http_error"
|
9
|
+
require "mail"
|
8
10
|
|
9
11
|
module Savon
|
10
12
|
class Operation
|
11
13
|
|
14
|
+
SOAP_REQUEST_TYPE = {
|
15
|
+
1 => "text/xml",
|
16
|
+
2 => "application/soap+xml"
|
17
|
+
}
|
18
|
+
|
12
19
|
def self.create(operation_name, wsdl, globals)
|
13
20
|
if wsdl.document?
|
14
21
|
ensure_name_is_symbol! operation_name
|
@@ -66,21 +73,7 @@ module Savon
|
|
66
73
|
private
|
67
74
|
|
68
75
|
def create_response(response)
|
69
|
-
|
70
|
-
Multipart::Response.new(response, @globals, @locals)
|
71
|
-
else
|
72
|
-
Response.new(response, @globals, @locals)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def multipart_supported?
|
77
|
-
return false unless @globals[:multipart] || @locals[:multipart]
|
78
|
-
|
79
|
-
if Savon.const_defined? :Multipart
|
80
|
-
true
|
81
|
-
else
|
82
|
-
raise 'Unable to find Savon::Multipart. Make sure the savon-multipart gem is installed and loaded.'
|
83
|
-
end
|
76
|
+
Response.new(response, @globals, @locals)
|
84
77
|
end
|
85
78
|
|
86
79
|
def set_locals(locals, block)
|
@@ -100,12 +93,22 @@ module Savon
|
|
100
93
|
|
101
94
|
request = SOAPRequest.new(@globals).build(
|
102
95
|
:soap_action => soap_action,
|
103
|
-
:cookies => @locals[:cookies]
|
96
|
+
:cookies => @locals[:cookies],
|
97
|
+
:headers => @locals[:headers]
|
104
98
|
)
|
105
99
|
|
106
100
|
request.url = endpoint
|
107
101
|
request.body = builder.to_s
|
108
102
|
|
103
|
+
if builder.multipart
|
104
|
+
request.gzip
|
105
|
+
request.headers["Content-Type"] = ["multipart/related",
|
106
|
+
"type=\"#{SOAP_REQUEST_TYPE[@globals[:soap_version]]}\"",
|
107
|
+
"start=\"#{builder.multipart[:start]}\"",
|
108
|
+
"boundary=\"#{builder.multipart[:multipart_boundary]}\""].join("; ")
|
109
|
+
request.headers["MIME-Version"] = "1.0"
|
110
|
+
end
|
111
|
+
|
109
112
|
# TODO: could HTTPI do this automatically in case the header
|
110
113
|
# was not specified manually? [dh, 2013-01-04]
|
111
114
|
request.headers["Content-Length"] = request.body.bytesize.to_s
|
@@ -118,11 +121,11 @@ module Savon
|
|
118
121
|
return if @locals.include?(:soap_action) && !@locals[:soap_action]
|
119
122
|
|
120
123
|
# get the soap_action from local options
|
121
|
-
|
124
|
+
@locals[:soap_action] ||
|
122
125
|
# with no local option, but a wsdl, ask it for the soap_action
|
123
|
-
|
126
|
+
@wsdl.document? && @wsdl.soap_action(@name.to_sym) ||
|
124
127
|
# if there is no soap_action up to this point, fallback to a simple default
|
125
|
-
|
128
|
+
Gyoku.xml_tag(@name, :key_converter => @globals[:convert_request_keys_to])
|
126
129
|
end
|
127
130
|
|
128
131
|
def endpoint
|