savon 2.16.0 → 2.17.4
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 +4 -4
- data/CHANGELOG.md +110 -7
- data/README.md +54 -48
- data/Rakefile +6 -2
- data/lib/savon/addressing.rb +60 -0
- data/lib/savon/block_interface.rb +3 -4
- data/lib/savon/builder.rb +54 -23
- data/lib/savon/client.rb +44 -13
- data/lib/savon/effective_options.rb +124 -0
- data/lib/savon/faraday_migration_hint.rb +186 -0
- data/lib/savon/header.rb +87 -40
- data/lib/savon/http_error.rb +8 -8
- data/lib/savon/log_message.rb +2 -3
- data/lib/savon/message.rb +6 -7
- data/lib/savon/mock/expectation.rb +37 -23
- data/lib/savon/mock/spec_helper.rb +7 -11
- data/lib/savon/mock.rb +1 -0
- data/lib/savon/model.rb +25 -25
- data/lib/savon/operation.rb +110 -74
- data/lib/savon/options.rb +274 -157
- data/lib/savon/qualified_message.rb +2 -1
- data/lib/savon/response.rb +40 -31
- data/lib/savon/soap_fault.rb +2 -3
- data/lib/savon/string_utils.rb +3 -4
- data/lib/savon/transport/faraday.rb +101 -0
- data/lib/savon/transport/httpi.rb +138 -0
- data/lib/savon/transport/logging.rb +60 -0
- data/lib/savon/transport/response.rb +73 -0
- data/lib/savon/version.rb +2 -1
- data/lib/savon.rb +2 -3
- metadata +85 -83
- data/lib/savon/request.rb +0 -113
- data/lib/savon/request_logger.rb +0 -54
data/lib/savon/options.rb
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require "logger"
|
|
3
4
|
require "httpi"
|
|
5
|
+
require "savon/faraday_migration_hint"
|
|
4
6
|
|
|
5
7
|
module Savon
|
|
8
|
+
# Base class for GlobalOptions and LocalOptions.
|
|
9
|
+
# Stores options in a hash, dispatches setter calls by method name,
|
|
10
|
+
# raises UnknownOptionError for anything not defined on the subclass.
|
|
6
11
|
class Options
|
|
7
|
-
|
|
8
12
|
def initialize(options = {})
|
|
9
13
|
@options = {}
|
|
10
14
|
assign options
|
|
@@ -18,7 +22,7 @@ module Savon
|
|
|
18
22
|
|
|
19
23
|
def []=(option, value)
|
|
20
24
|
value = [value].flatten
|
|
21
|
-
|
|
25
|
+
send(option, *value)
|
|
22
26
|
end
|
|
23
27
|
|
|
24
28
|
def include?(option)
|
|
@@ -29,7 +33,7 @@ module Savon
|
|
|
29
33
|
|
|
30
34
|
def assign(options)
|
|
31
35
|
options.each do |option, value|
|
|
32
|
-
|
|
36
|
+
send(option, value)
|
|
33
37
|
end
|
|
34
38
|
end
|
|
35
39
|
|
|
@@ -38,6 +42,8 @@ module Savon
|
|
|
38
42
|
end
|
|
39
43
|
end
|
|
40
44
|
|
|
45
|
+
# Options available in both GlobalOptions and LocalOptions.
|
|
46
|
+
# Currently covers WSSE authentication and timestamp headers.
|
|
41
47
|
module SharedOptions
|
|
42
48
|
# WSSE auth credentials for Akami.
|
|
43
49
|
# Local will override the global wsse_auth value, e.g.
|
|
@@ -46,11 +52,12 @@ module Savon
|
|
|
46
52
|
# global == [user, pass] && local == nil => [user, pass]
|
|
47
53
|
def wsse_auth(*credentials)
|
|
48
54
|
credentials.flatten!
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
@options[:wsse_auth] =
|
|
56
|
+
if credentials.size == 1
|
|
57
|
+
credentials.first
|
|
58
|
+
else
|
|
59
|
+
credentials
|
|
60
|
+
end
|
|
54
61
|
end
|
|
55
62
|
|
|
56
63
|
# Instruct Akami to enable wsu:Timestamp headers.
|
|
@@ -67,35 +74,186 @@ module Savon
|
|
|
67
74
|
end
|
|
68
75
|
end
|
|
69
76
|
|
|
77
|
+
# Options that belong to HTTPI's transport layer.
|
|
78
|
+
#
|
|
79
|
+
# They still work with the default HTTPI transport. With `transport: :faraday`,
|
|
80
|
+
# Savon does not translate them because Faraday exposes its own setup API for
|
|
81
|
+
# proxy, timeout, TLS, auth, redirects, and adapter choices.
|
|
82
|
+
module HTTPITransportOptions
|
|
83
|
+
TRANSPORT_DEFAULTS = {
|
|
84
|
+
adapter: nil,
|
|
85
|
+
follow_redirects: false
|
|
86
|
+
}.freeze
|
|
87
|
+
|
|
88
|
+
# These are rejected for `transport: :faraday` once the caller has set a
|
|
89
|
+
# non-default value. The error points to the matching Faraday setup.
|
|
90
|
+
FARADAY_INCOMPATIBLE_GLOBALS = FaradayMigrationHint::OPTIONS
|
|
91
|
+
|
|
92
|
+
# Runs after all global options have been assigned, including options set in
|
|
93
|
+
# the client block. Reports every HTTPI-only option in one error so callers
|
|
94
|
+
# can move their transport setup to Faraday in one pass.
|
|
95
|
+
def validate_transport!
|
|
96
|
+
return unless self[:transport] == :faraday
|
|
97
|
+
|
|
98
|
+
unless faraday_loaded?
|
|
99
|
+
raise InitializationError,
|
|
100
|
+
"transport: :faraday requires the faraday gem.\n" \
|
|
101
|
+
"Add to your Gemfile: gem 'faraday'"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
violations = FARADAY_INCOMPATIBLE_GLOBALS.filter_map { |option|
|
|
105
|
+
next unless include?(option)
|
|
106
|
+
next if default_transport_option?(option)
|
|
107
|
+
|
|
108
|
+
FaradayMigrationHint.new(option, self[option]).message
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return if violations.empty?
|
|
112
|
+
|
|
113
|
+
raise InitializationError,
|
|
114
|
+
"The following options are not supported with transport: :faraday:\n#{violations.join("\n")}"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Proxy server to use for all requests.
|
|
118
|
+
def proxy(proxy)
|
|
119
|
+
@options[:proxy] = proxy unless proxy.nil?
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Open timeout in seconds.
|
|
123
|
+
def open_timeout(open_timeout)
|
|
124
|
+
@options[:open_timeout] = open_timeout
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Read timeout in seconds.
|
|
128
|
+
def read_timeout(read_timeout)
|
|
129
|
+
@options[:read_timeout] = read_timeout
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Write timeout in seconds.
|
|
133
|
+
def write_timeout(write_timeout)
|
|
134
|
+
@options[:write_timeout] = write_timeout
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Specifies the SSL version to use.
|
|
138
|
+
def ssl_version(version)
|
|
139
|
+
@options[:ssl_version] = version
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Specifies the minimum SSL version to use.
|
|
143
|
+
def ssl_min_version(version)
|
|
144
|
+
@options[:ssl_min_version] = version
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Specifies the maximum SSL version to use.
|
|
148
|
+
def ssl_max_version(version)
|
|
149
|
+
@options[:ssl_max_version] = version
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Whether and how to verify the SSL connection.
|
|
153
|
+
def ssl_verify_mode(verify_mode)
|
|
154
|
+
@options[:ssl_verify_mode] = verify_mode
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Sets the cert key file to use.
|
|
158
|
+
def ssl_cert_key_file(file)
|
|
159
|
+
@options[:ssl_cert_key_file] = file
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Sets the cert key to use.
|
|
163
|
+
def ssl_cert_key(key)
|
|
164
|
+
@options[:ssl_cert_key] = key
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Sets the cert key password to use.
|
|
168
|
+
def ssl_cert_key_password(password)
|
|
169
|
+
@options[:ssl_cert_key_password] = password
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Sets the cert file to use.
|
|
173
|
+
def ssl_cert_file(file)
|
|
174
|
+
@options[:ssl_cert_file] = file
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Sets the cert to use.
|
|
178
|
+
def ssl_cert(cert)
|
|
179
|
+
@options[:ssl_cert] = cert
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Sets the CA cert file to use.
|
|
183
|
+
def ssl_ca_cert_file(file)
|
|
184
|
+
@options[:ssl_ca_cert_file] = file
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Sets the CA cert to use.
|
|
188
|
+
def ssl_ca_cert(cert)
|
|
189
|
+
@options[:ssl_ca_cert] = cert
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Sets the SSL ciphers to use.
|
|
193
|
+
def ssl_ciphers(ciphers)
|
|
194
|
+
@options[:ssl_ciphers] = ciphers
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Sets the CA cert path.
|
|
198
|
+
def ssl_ca_cert_path(path)
|
|
199
|
+
@options[:ssl_ca_cert_path] = path
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Sets the SSL cert store.
|
|
203
|
+
def ssl_cert_store(store)
|
|
204
|
+
@options[:ssl_cert_store] = store
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# HTTP basic auth credentials.
|
|
208
|
+
def basic_auth(*credentials)
|
|
209
|
+
@options[:basic_auth] = credentials.flatten
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# HTTP digest auth credentials.
|
|
213
|
+
def digest_auth(*credentials)
|
|
214
|
+
@options[:digest_auth] = credentials.flatten
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# NTLM auth credentials.
|
|
218
|
+
def ntlm(*credentials)
|
|
219
|
+
@options[:ntlm] = credentials.flatten
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# Instruct requests to follow HTTP redirects.
|
|
223
|
+
def follow_redirects(follow_redirects)
|
|
224
|
+
@options[:follow_redirects] = follow_redirects
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# Instruct Savon which HTTPI adapter to use instead of the default.
|
|
228
|
+
def adapter(adapter)
|
|
229
|
+
@options[:adapter] = adapter
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
private
|
|
233
|
+
|
|
234
|
+
def default_transport_option?(option)
|
|
235
|
+
TRANSPORT_DEFAULTS.key?(option) && self[option] == TRANSPORT_DEFAULTS[option]
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# Attempts to load faraday. Returns true if available, false on LoadError.
|
|
239
|
+
def faraday_loaded?
|
|
240
|
+
require "faraday"
|
|
241
|
+
true
|
|
242
|
+
rescue LoadError
|
|
243
|
+
false
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# Client-level options applied to every request made by a Savon::Client instance.
|
|
248
|
+
# Covers service location, SOAP configuration, logging, response parsing,
|
|
249
|
+
# and transport selection. HTTPI-specific options (proxy, timeouts, SSL, auth)
|
|
250
|
+
# come from HTTPITransportOptions.
|
|
70
251
|
class GlobalOptions < Options
|
|
71
252
|
include SharedOptions
|
|
253
|
+
include HTTPITransportOptions
|
|
72
254
|
|
|
73
255
|
def initialize(options = {})
|
|
74
256
|
@option_type = :global
|
|
75
|
-
|
|
76
|
-
defaults = {
|
|
77
|
-
:encoding => "UTF-8",
|
|
78
|
-
:soap_version => 1,
|
|
79
|
-
:namespaces => {},
|
|
80
|
-
:logger => Logger.new($stdout),
|
|
81
|
-
:log => false,
|
|
82
|
-
:log_headers => true,
|
|
83
|
-
:filters => [],
|
|
84
|
-
:pretty_print_xml => false,
|
|
85
|
-
:raise_errors => true,
|
|
86
|
-
:strip_namespaces => true,
|
|
87
|
-
:delete_namespace_attributes => false,
|
|
88
|
-
:convert_response_tags_to => lambda { |tag| StringUtils.snakecase(tag).to_sym},
|
|
89
|
-
:convert_attributes_to => lambda { |k,v| [k,v] },
|
|
90
|
-
:multipart => false,
|
|
91
|
-
:adapter => nil,
|
|
92
|
-
:use_wsa_headers => false,
|
|
93
|
-
:no_message_tag => false,
|
|
94
|
-
:follow_redirects => false,
|
|
95
|
-
:unwrap => false,
|
|
96
|
-
:host => nil
|
|
97
|
-
}
|
|
98
|
-
|
|
99
257
|
options = defaults.merge(options)
|
|
100
258
|
|
|
101
259
|
# this option is a shortcut on the logger which needs to be set
|
|
@@ -112,7 +270,7 @@ module Savon
|
|
|
112
270
|
@options[:wsdl] = wsdl_address
|
|
113
271
|
end
|
|
114
272
|
|
|
115
|
-
#
|
|
273
|
+
# Set a different host for actions in the WSDL.
|
|
116
274
|
def host(host)
|
|
117
275
|
@options[:host] = host
|
|
118
276
|
end
|
|
@@ -127,7 +285,7 @@ module Savon
|
|
|
127
285
|
@options[:namespace] = namespace
|
|
128
286
|
end
|
|
129
287
|
|
|
130
|
-
# The namespace
|
|
288
|
+
# The namespace identifier.
|
|
131
289
|
def namespace_identifier(identifier)
|
|
132
290
|
@options[:namespace_identifier] = identifier
|
|
133
291
|
end
|
|
@@ -137,31 +295,11 @@ module Savon
|
|
|
137
295
|
@options[:namespaces] = namespaces
|
|
138
296
|
end
|
|
139
297
|
|
|
140
|
-
#
|
|
141
|
-
def proxy(proxy)
|
|
142
|
-
@options[:proxy] = proxy unless proxy.nil?
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
# A Hash of HTTP headers.
|
|
298
|
+
# A Hash of HTTP headers sent with every request.
|
|
146
299
|
def headers(headers)
|
|
147
300
|
@options[:headers] = headers
|
|
148
301
|
end
|
|
149
302
|
|
|
150
|
-
# Open timeout in seconds.
|
|
151
|
-
def open_timeout(open_timeout)
|
|
152
|
-
@options[:open_timeout] = open_timeout
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
# Read timeout in seconds.
|
|
156
|
-
def read_timeout(read_timeout)
|
|
157
|
-
@options[:read_timeout] = read_timeout
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
# Write timeout in seconds.
|
|
161
|
-
def write_timeout(write_timeout)
|
|
162
|
-
@options[:write_timeout] = write_timeout
|
|
163
|
-
end
|
|
164
|
-
|
|
165
303
|
# The encoding to use. Defaults to "UTF-8".
|
|
166
304
|
def encoding(encoding)
|
|
167
305
|
@options[:encoding] = encoding
|
|
@@ -210,7 +348,7 @@ module Savon
|
|
|
210
348
|
|
|
211
349
|
# Changes the Logger's log level.
|
|
212
350
|
def log_level(level)
|
|
213
|
-
levels = { :
|
|
351
|
+
levels = { debug: 0, info: 1, warn: 2, error: 3, fatal: 4 }
|
|
214
352
|
|
|
215
353
|
unless levels.include? level
|
|
216
354
|
raise ArgumentError, "Invalid log level: #{level.inspect}\n" \
|
|
@@ -220,7 +358,7 @@ module Savon
|
|
|
220
358
|
@options[:logger].level = levels[level]
|
|
221
359
|
end
|
|
222
360
|
|
|
223
|
-
#
|
|
361
|
+
# Whether to log headers.
|
|
224
362
|
def log_headers(log_headers)
|
|
225
363
|
@options[:log_headers] = log_headers
|
|
226
364
|
end
|
|
@@ -235,90 +373,6 @@ module Savon
|
|
|
235
373
|
@options[:pretty_print_xml] = pretty_print_xml
|
|
236
374
|
end
|
|
237
375
|
|
|
238
|
-
# Specifies the SSL version to use.
|
|
239
|
-
def ssl_version(version)
|
|
240
|
-
@options[:ssl_version] = version
|
|
241
|
-
end
|
|
242
|
-
|
|
243
|
-
# Specifies the SSL version to use.
|
|
244
|
-
def ssl_min_version(version)
|
|
245
|
-
@options[:ssl_min_version] = version
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
# Specifies the SSL version to use.
|
|
249
|
-
def ssl_max_version(version)
|
|
250
|
-
@options[:ssl_max_version] = version
|
|
251
|
-
end
|
|
252
|
-
|
|
253
|
-
# Whether and how to to verify the connection.
|
|
254
|
-
def ssl_verify_mode(verify_mode)
|
|
255
|
-
@options[:ssl_verify_mode] = verify_mode
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
# Sets the cert key file to use.
|
|
259
|
-
def ssl_cert_key_file(file)
|
|
260
|
-
@options[:ssl_cert_key_file] = file
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
# Sets the cert key to use.
|
|
264
|
-
def ssl_cert_key(key)
|
|
265
|
-
@options[:ssl_cert_key] = key
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
# Sets the cert key password to use.
|
|
269
|
-
def ssl_cert_key_password(password)
|
|
270
|
-
@options[:ssl_cert_key_password] = password
|
|
271
|
-
end
|
|
272
|
-
|
|
273
|
-
# Sets the cert file to use.
|
|
274
|
-
def ssl_cert_file(file)
|
|
275
|
-
@options[:ssl_cert_file] = file
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
# Sets the cert to use.
|
|
279
|
-
def ssl_cert(cert)
|
|
280
|
-
@options[:ssl_cert] = cert
|
|
281
|
-
end
|
|
282
|
-
|
|
283
|
-
# Sets the ca cert file to use.
|
|
284
|
-
def ssl_ca_cert_file(file)
|
|
285
|
-
@options[:ssl_ca_cert_file] = file
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
# Sets the ca cert to use.
|
|
289
|
-
def ssl_ca_cert(cert)
|
|
290
|
-
@options[:ssl_ca_cert] = cert
|
|
291
|
-
end
|
|
292
|
-
|
|
293
|
-
def ssl_ciphers(ciphers)
|
|
294
|
-
@options[:ssl_ciphers] = ciphers
|
|
295
|
-
end
|
|
296
|
-
|
|
297
|
-
# Sets the ca cert path.
|
|
298
|
-
def ssl_ca_cert_path(path)
|
|
299
|
-
@options[:ssl_ca_cert_path] = path
|
|
300
|
-
end
|
|
301
|
-
|
|
302
|
-
# Sets the ssl cert store.
|
|
303
|
-
def ssl_cert_store(store)
|
|
304
|
-
@options[:ssl_cert_store] = store
|
|
305
|
-
end
|
|
306
|
-
|
|
307
|
-
# HTTP basic auth credentials.
|
|
308
|
-
def basic_auth(*credentials)
|
|
309
|
-
@options[:basic_auth] = credentials.flatten
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
# HTTP digest auth credentials.
|
|
313
|
-
def digest_auth(*credentials)
|
|
314
|
-
@options[:digest_auth] = credentials.flatten
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
# NTLM auth credentials.
|
|
318
|
-
def ntlm(*credentials)
|
|
319
|
-
@options[:ntlm] = credentials.flatten
|
|
320
|
-
end
|
|
321
|
-
|
|
322
376
|
# Instruct Nori whether to strip namespaces from XML nodes.
|
|
323
377
|
def strip_namespaces(strip_namespaces)
|
|
324
378
|
@options[:strip_namespaces] = strip_namespaces
|
|
@@ -329,57 +383,113 @@ module Savon
|
|
|
329
383
|
@options[:delete_namespace_attributes] = delete_namespace_attributes
|
|
330
384
|
end
|
|
331
385
|
|
|
386
|
+
# The value Nori assigns to empty XML tags in the SOAP response.
|
|
387
|
+
# Defaults to nil, matching Nori's default; set to "" to map empty tags
|
|
388
|
+
# to an empty String instead.
|
|
389
|
+
def empty_tag_value(value)
|
|
390
|
+
@options[:empty_tag_value] = value
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
# Instruct Nori whether to convert dashes in response tag names to
|
|
394
|
+
# underscores before they become Hash keys. Defaults to true.
|
|
395
|
+
def convert_dashes_to_underscores(convert)
|
|
396
|
+
@options[:convert_dashes_to_underscores] = convert
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
# Instruct Nori whether to scrub invalid byte sequences from the response
|
|
400
|
+
# body before parsing it. Defaults to true, which lets responses containing
|
|
401
|
+
# invalid characters still be parsed.
|
|
402
|
+
def scrub_xml(scrub)
|
|
403
|
+
@options[:scrub_xml] = scrub
|
|
404
|
+
end
|
|
405
|
+
|
|
332
406
|
# Tell Gyoku how to convert Hash key Symbols to XML tags.
|
|
333
407
|
# Accepts one of :lower_camelcase, :camelcase, :upcase, or :none.
|
|
334
408
|
def convert_request_keys_to(converter)
|
|
335
409
|
@options[:convert_request_keys_to] = converter
|
|
336
410
|
end
|
|
337
411
|
|
|
338
|
-
# Tell Gyoku to unwrap Array of Hashes
|
|
339
|
-
# Accepts a boolean,
|
|
412
|
+
# Tell Gyoku to unwrap Array of Hashes.
|
|
413
|
+
# Accepts a boolean, defaults to false.
|
|
340
414
|
def unwrap(unwrap)
|
|
341
415
|
@options[:unwrap] = unwrap
|
|
342
416
|
end
|
|
343
417
|
|
|
344
418
|
# Tell Nori how to convert XML tags from the SOAP response into Hash keys.
|
|
345
419
|
# Accepts a lambda or a block which receives an XML tag and returns a Hash key.
|
|
346
|
-
# Defaults to
|
|
420
|
+
# Defaults to converting tags to snakecase Symbols.
|
|
347
421
|
def convert_response_tags_to(converter = nil, &block)
|
|
348
422
|
@options[:convert_response_tags_to] = block || converter
|
|
349
423
|
end
|
|
350
424
|
|
|
351
425
|
# Tell Nori how to convert XML attributes on tags from the SOAP response into Hash keys.
|
|
352
426
|
# Accepts a lambda or a block which receives an XML tag and returns a Hash key.
|
|
353
|
-
# Defaults to doing nothing
|
|
427
|
+
# Defaults to doing nothing.
|
|
354
428
|
def convert_attributes_to(converter = nil, &block)
|
|
355
429
|
@options[:convert_attributes_to] = block || converter
|
|
356
430
|
end
|
|
357
431
|
|
|
358
432
|
# Instruct Savon to create a multipart response if available.
|
|
359
433
|
def multipart(multipart)
|
|
434
|
+
if multipart
|
|
435
|
+
warn "The global :multipart option has been a no-op since v2.13.0. " \
|
|
436
|
+
"Savon detects whether the response is multipart by checking if the " \
|
|
437
|
+
"response Content-Type header contains 'multipart'. You can remove" \
|
|
438
|
+
"this option from your code to make this warning disappear.", uplevel: 1
|
|
439
|
+
end
|
|
360
440
|
@options[:multipart] = multipart
|
|
361
441
|
end
|
|
362
442
|
|
|
363
|
-
# Instruct Savon what HTTPI adapter it should use instead of default
|
|
364
|
-
def adapter(adapter)
|
|
365
|
-
@options[:adapter] = adapter
|
|
366
|
-
end
|
|
367
|
-
|
|
368
443
|
# Enable inclusion of WS-Addressing headers.
|
|
369
444
|
def use_wsa_headers(use)
|
|
370
445
|
@options[:use_wsa_headers] = use
|
|
371
446
|
end
|
|
372
447
|
|
|
448
|
+
# Suppress the message tag wrapper around the SOAP body.
|
|
373
449
|
def no_message_tag(bool)
|
|
374
450
|
@options[:no_message_tag] = bool
|
|
375
451
|
end
|
|
376
452
|
|
|
377
|
-
#
|
|
378
|
-
|
|
379
|
-
|
|
453
|
+
# HTTP transport to use. Accepts :httpi (default) or :faraday.
|
|
454
|
+
# With :faraday, set proxy, timeout, TLS, auth, redirect, and adapter
|
|
455
|
+
# details on `client.faraday`; the HTTPI transport options are not copied.
|
|
456
|
+
def transport(transport)
|
|
457
|
+
@options[:transport] = transport
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
private
|
|
461
|
+
|
|
462
|
+
# The default value for every global option.
|
|
463
|
+
def defaults
|
|
464
|
+
HTTPITransportOptions::TRANSPORT_DEFAULTS.merge(
|
|
465
|
+
encoding: "UTF-8",
|
|
466
|
+
soap_version: 1,
|
|
467
|
+
namespaces: {},
|
|
468
|
+
logger: Logger.new($stdout),
|
|
469
|
+
log: false,
|
|
470
|
+
log_headers: true,
|
|
471
|
+
filters: [],
|
|
472
|
+
pretty_print_xml: false,
|
|
473
|
+
raise_errors: true,
|
|
474
|
+
strip_namespaces: true,
|
|
475
|
+
delete_namespace_attributes: false,
|
|
476
|
+
empty_tag_value: nil,
|
|
477
|
+
convert_dashes_to_underscores: true,
|
|
478
|
+
scrub_xml: true,
|
|
479
|
+
convert_response_tags_to: ->(tag) { StringUtils.snakecase(tag).to_sym },
|
|
480
|
+
convert_attributes_to: ->(k, v) { [k, v] },
|
|
481
|
+
multipart: false,
|
|
482
|
+
use_wsa_headers: false,
|
|
483
|
+
no_message_tag: false,
|
|
484
|
+
unwrap: false,
|
|
485
|
+
host: nil,
|
|
486
|
+
transport: :httpi
|
|
487
|
+
)
|
|
380
488
|
end
|
|
381
489
|
end
|
|
382
490
|
|
|
491
|
+
# Per-request options passed to client.call.
|
|
492
|
+
# Overrides or extends the matching GlobalOptions for a single SOAP operation.
|
|
383
493
|
class LocalOptions < Options
|
|
384
494
|
include SharedOptions
|
|
385
495
|
|
|
@@ -387,9 +497,9 @@ module Savon
|
|
|
387
497
|
@option_type = :local
|
|
388
498
|
|
|
389
499
|
defaults = {
|
|
390
|
-
:
|
|
391
|
-
:
|
|
392
|
-
:
|
|
500
|
+
advanced_typecasting: true,
|
|
501
|
+
response_parser: :nokogiri,
|
|
502
|
+
multipart: false
|
|
393
503
|
}
|
|
394
504
|
|
|
395
505
|
super defaults.merge(options)
|
|
@@ -397,7 +507,7 @@ module Savon
|
|
|
397
507
|
|
|
398
508
|
# The local SOAP header. Expected to be a Hash or respond to #to_s.
|
|
399
509
|
# Will be merged with the global SOAP header if both are Hashes.
|
|
400
|
-
# Otherwise the local option will be
|
|
510
|
+
# Otherwise the local option will be preferred.
|
|
401
511
|
def soap_header(header)
|
|
402
512
|
@options[:soap_header] = header
|
|
403
513
|
end
|
|
@@ -479,9 +589,16 @@ module Savon
|
|
|
479
589
|
|
|
480
590
|
# Instruct Savon to create a multipart response if available.
|
|
481
591
|
def multipart(multipart)
|
|
592
|
+
if multipart
|
|
593
|
+
warn "The local :multipart option has been a no-op since v2.13.0. " \
|
|
594
|
+
"Savon detects whether the response is multipart by checking if the " \
|
|
595
|
+
"response Content-Type header contains 'multipart'. You can remove" \
|
|
596
|
+
"this option from your code to make this warning disappear.", uplevel: 1
|
|
597
|
+
end
|
|
482
598
|
@options[:multipart] = multipart
|
|
483
599
|
end
|
|
484
600
|
|
|
601
|
+
# Per-request HTTP headers. Merged with global headers for each request.
|
|
485
602
|
def headers(headers)
|
|
486
603
|
@options[:headers] = headers
|
|
487
604
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require "gyoku"
|
|
3
4
|
|
|
4
5
|
module Savon
|
|
@@ -37,7 +38,7 @@ module Savon
|
|
|
37
38
|
private
|
|
38
39
|
|
|
39
40
|
def translate_tag(key)
|
|
40
|
-
Gyoku.xml_tag(key, :
|
|
41
|
+
Gyoku.xml_tag(key, key_converter: @key_converter).to_s
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
def add_namespaces_to_values(values, path)
|