savon-ng-1.6 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.travis.yml +15 -0
- data/.yardopts +6 -0
- data/CHANGELOG.md +1024 -0
- data/CONTRIBUTING.md +46 -0
- data/Gemfile +8 -0
- data/LICENSE +20 -0
- data/README.md +81 -0
- data/Rakefile +14 -0
- data/donate.png +0 -0
- data/lib/savon/block_interface.rb +26 -0
- data/lib/savon/builder.rb +166 -0
- data/lib/savon/client.rb +88 -0
- data/lib/savon/core_ext/string.rb +29 -0
- data/lib/savon/header.rb +70 -0
- data/lib/savon/http_error.rb +27 -0
- data/lib/savon/log_message.rb +48 -0
- data/lib/savon/message.rb +36 -0
- data/lib/savon/mock/expectation.rb +71 -0
- data/lib/savon/mock/spec_helper.rb +62 -0
- data/lib/savon/mock.rb +5 -0
- data/lib/savon/model.rb +80 -0
- data/lib/savon/operation.rb +127 -0
- data/lib/savon/options.rb +330 -0
- data/lib/savon/qualified_message.rb +49 -0
- data/lib/savon/request.rb +89 -0
- data/lib/savon/request_logger.rb +48 -0
- data/lib/savon/response.rb +112 -0
- data/lib/savon/soap_fault.rb +48 -0
- data/lib/savon/version.rb +5 -0
- data/lib/savon.rb +27 -0
- data/savon.gemspec +47 -0
- data/spec/fixtures/gzip/message.gz +0 -0
- data/spec/fixtures/response/another_soap_fault.xml +14 -0
- data/spec/fixtures/response/authentication.xml +14 -0
- data/spec/fixtures/response/header.xml +13 -0
- data/spec/fixtures/response/list.xml +18 -0
- data/spec/fixtures/response/multi_ref.xml +39 -0
- data/spec/fixtures/response/soap_fault.xml +8 -0
- data/spec/fixtures/response/soap_fault12.xml +18 -0
- data/spec/fixtures/response/taxcloud.xml +1 -0
- data/spec/fixtures/ssl/client_cert.pem +16 -0
- data/spec/fixtures/ssl/client_encrypted_key.pem +30 -0
- data/spec/fixtures/ssl/client_encrypted_key_cert.pem +24 -0
- data/spec/fixtures/ssl/client_key.pem +15 -0
- data/spec/fixtures/wsdl/authentication.xml +63 -0
- data/spec/fixtures/wsdl/betfair.xml +2981 -0
- data/spec/fixtures/wsdl/edialog.xml +15416 -0
- data/spec/fixtures/wsdl/interhome.xml +2137 -0
- data/spec/fixtures/wsdl/lower_camel.xml +52 -0
- data/spec/fixtures/wsdl/multiple_namespaces.xml +92 -0
- data/spec/fixtures/wsdl/multiple_types.xml +60 -0
- data/spec/fixtures/wsdl/taxcloud.xml +934 -0
- data/spec/fixtures/wsdl/team_software.xml +1 -0
- data/spec/fixtures/wsdl/vies.xml +176 -0
- data/spec/fixtures/wsdl/wasmuth.xml +153 -0
- data/spec/integration/email_example_spec.rb +32 -0
- data/spec/integration/ratp_example_spec.rb +28 -0
- data/spec/integration/stockquote_example_spec.rb +28 -0
- data/spec/integration/support/application.rb +82 -0
- data/spec/integration/support/server.rb +84 -0
- data/spec/integration/temperature_example_spec.rb +46 -0
- data/spec/integration/zipcode_example_spec.rb +42 -0
- data/spec/savon/builder_spec.rb +86 -0
- data/spec/savon/client_spec.rb +193 -0
- data/spec/savon/core_ext/string_spec.rb +37 -0
- data/spec/savon/features/message_tag_spec.rb +61 -0
- data/spec/savon/http_error_spec.rb +49 -0
- data/spec/savon/log_message_spec.rb +33 -0
- data/spec/savon/message_spec.rb +40 -0
- data/spec/savon/mock_spec.rb +157 -0
- data/spec/savon/model_spec.rb +154 -0
- data/spec/savon/observers_spec.rb +92 -0
- data/spec/savon/operation_spec.rb +211 -0
- data/spec/savon/options_spec.rb +772 -0
- data/spec/savon/request_spec.rb +493 -0
- data/spec/savon/response_spec.rb +258 -0
- data/spec/savon/soap_fault_spec.rb +126 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/support/endpoint.rb +25 -0
- data/spec/support/fixture.rb +39 -0
- data/spec/support/integration.rb +9 -0
- data/spec/support/stdout.rb +25 -0
- metadata +308 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
require "httpi"
|
2
|
+
|
3
|
+
module Savon
|
4
|
+
class MockExpectation
|
5
|
+
|
6
|
+
def initialize(operation_name)
|
7
|
+
@expected = { :operation_name => operation_name }
|
8
|
+
@actual = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def with(locals)
|
12
|
+
@expected[:message] = locals[:message]
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
def returns(response)
|
17
|
+
response = { :code => 200, :headers => {}, :body => response } if response.kind_of?(String)
|
18
|
+
@response = response
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def actual(operation_name, builder, globals, locals)
|
23
|
+
@actual = {
|
24
|
+
:operation_name => operation_name,
|
25
|
+
:message => locals[:message]
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def verify!
|
30
|
+
unless @actual
|
31
|
+
raise ExpectationError, "Expected a request to the #{@expected[:operation_name].inspect} operation, " \
|
32
|
+
"but no request was executed."
|
33
|
+
end
|
34
|
+
|
35
|
+
verify_operation_name!
|
36
|
+
verify_message!
|
37
|
+
end
|
38
|
+
|
39
|
+
def response!
|
40
|
+
unless @response
|
41
|
+
raise ExpectationError, "This expectation was not set up with a response."
|
42
|
+
end
|
43
|
+
|
44
|
+
HTTPI::Response.new(@response[:code], @response[:headers], @response[:body])
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def verify_operation_name!
|
50
|
+
unless @expected[:operation_name] == @actual[:operation_name]
|
51
|
+
raise ExpectationError, "Expected a request to the #{@expected[:operation_name].inspect} operation.\n" \
|
52
|
+
"Received a request to the #{@actual[:operation_name].inspect} operation instead."
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def verify_message!
|
57
|
+
return if @expected[:message] == :any
|
58
|
+
unless @expected[:message] == @actual[:message]
|
59
|
+
expected_message = " with this message: #{@expected[:message].inspect}" if @expected[:message]
|
60
|
+
expected_message ||= " with no message."
|
61
|
+
|
62
|
+
actual_message = " with this message: #{@actual[:message].inspect}" if @actual[:message]
|
63
|
+
actual_message ||= " with no message."
|
64
|
+
|
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}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "savon/mock"
|
2
|
+
|
3
|
+
module Savon
|
4
|
+
module SpecHelper
|
5
|
+
|
6
|
+
class Interface
|
7
|
+
|
8
|
+
def mock!
|
9
|
+
Savon.observers << self
|
10
|
+
end
|
11
|
+
|
12
|
+
def unmock!
|
13
|
+
Savon.observers.clear
|
14
|
+
end
|
15
|
+
|
16
|
+
def expects(operation_name)
|
17
|
+
expectation = MockExpectation.new(operation_name)
|
18
|
+
expectations << expectation
|
19
|
+
expectation
|
20
|
+
end
|
21
|
+
|
22
|
+
def expectations
|
23
|
+
@expectations ||= []
|
24
|
+
end
|
25
|
+
|
26
|
+
def notify(operation_name, builder, globals, locals)
|
27
|
+
expectation = expectations.shift
|
28
|
+
|
29
|
+
if expectation
|
30
|
+
expectation.actual(operation_name, builder, globals, locals)
|
31
|
+
|
32
|
+
expectation.verify!
|
33
|
+
expectation.response!
|
34
|
+
else
|
35
|
+
raise ExpectationError, "Unexpected request to the #{operation_name.inspect} operation."
|
36
|
+
end
|
37
|
+
rescue ExpectationError
|
38
|
+
@expectations.clear
|
39
|
+
raise
|
40
|
+
end
|
41
|
+
|
42
|
+
def verify!
|
43
|
+
return if expectations.empty?
|
44
|
+
expectations.each(&:verify!)
|
45
|
+
rescue ExpectationError
|
46
|
+
@expectations.clear
|
47
|
+
raise
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
def savon
|
53
|
+
@savon ||= Interface.new
|
54
|
+
end
|
55
|
+
|
56
|
+
def verify_mocks_for_rspec
|
57
|
+
super if defined? super
|
58
|
+
savon.verify!
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
data/lib/savon/mock.rb
ADDED
data/lib/savon/model.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
module Savon
|
2
|
+
module Model
|
3
|
+
|
4
|
+
def self.extended(base)
|
5
|
+
base.setup
|
6
|
+
end
|
7
|
+
|
8
|
+
def setup
|
9
|
+
class_operation_module
|
10
|
+
instance_operation_module
|
11
|
+
end
|
12
|
+
|
13
|
+
# Accepts one or more SOAP operations and generates both class and instance methods named
|
14
|
+
# after the given operations. Each generated method accepts an optional SOAP message Hash.
|
15
|
+
def operations(*operations)
|
16
|
+
operations.each do |operation|
|
17
|
+
define_class_operation(operation)
|
18
|
+
define_instance_operation(operation)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
# Defines a class-level SOAP operation.
|
25
|
+
def define_class_operation(operation)
|
26
|
+
class_operation_module.module_eval %{
|
27
|
+
def #{operation.to_s.snakecase}(locals = {})
|
28
|
+
client.call #{operation.inspect}, locals
|
29
|
+
end
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
# Defines an instance-level SOAP operation.
|
34
|
+
def define_instance_operation(operation)
|
35
|
+
instance_operation_module.module_eval %{
|
36
|
+
def #{operation.to_s.snakecase}(locals = {})
|
37
|
+
self.class.#{operation.to_s.snakecase} locals
|
38
|
+
end
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
# Class methods.
|
43
|
+
def class_operation_module
|
44
|
+
@class_operation_module ||= Module.new {
|
45
|
+
|
46
|
+
def client(globals = {})
|
47
|
+
@client ||= Savon::Client.new(globals)
|
48
|
+
rescue InitializationError
|
49
|
+
raise_initialization_error!
|
50
|
+
end
|
51
|
+
|
52
|
+
def global(option, *value)
|
53
|
+
client.globals[option] = value
|
54
|
+
end
|
55
|
+
|
56
|
+
def raise_initialization_error!
|
57
|
+
raise InitializationError,
|
58
|
+
"Expected the model to be initialized with either a WSDL document or the SOAP endpoint and target namespace options.\n" \
|
59
|
+
"Make sure to setup the model by calling the .client class method before calling the .global method.\n\n" \
|
60
|
+
"client(wsdl: '/Users/me/project/service.wsdl') # to use a local WSDL document\n" \
|
61
|
+
"client(wsdl: 'http://example.com?wsdl') # to use a remote WSDL document\n" \
|
62
|
+
"client(endpoint: 'http://example.com', namespace: 'http://v1.example.com') # if you don't have a WSDL document"
|
63
|
+
end
|
64
|
+
|
65
|
+
}.tap { |mod| extend(mod) }
|
66
|
+
end
|
67
|
+
|
68
|
+
# Instance methods.
|
69
|
+
def instance_operation_module
|
70
|
+
@instance_operation_module ||= Module.new {
|
71
|
+
|
72
|
+
def client
|
73
|
+
self.class.client
|
74
|
+
end
|
75
|
+
|
76
|
+
}.tap { |mod| include(mod) }
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require "savon/options"
|
2
|
+
require "savon/block_interface"
|
3
|
+
require "savon/request"
|
4
|
+
require "savon/builder"
|
5
|
+
require "savon/response"
|
6
|
+
require "savon/request_logger"
|
7
|
+
|
8
|
+
module Savon
|
9
|
+
class Operation
|
10
|
+
|
11
|
+
def self.create(operation_name, wsdl, globals)
|
12
|
+
if wsdl.document?
|
13
|
+
ensure_name_is_symbol! operation_name
|
14
|
+
ensure_exists! operation_name, wsdl
|
15
|
+
end
|
16
|
+
|
17
|
+
new(operation_name, wsdl, globals)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.ensure_exists!(operation_name, wsdl)
|
21
|
+
unless wsdl.soap_actions.include? operation_name
|
22
|
+
raise UnknownOperationError, "Unable to find SOAP operation: #{operation_name.inspect}\n" \
|
23
|
+
"Operations provided by your service: #{wsdl.soap_actions.inspect}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.ensure_name_is_symbol!(operation_name)
|
28
|
+
unless operation_name.kind_of? Symbol
|
29
|
+
raise ArgumentError, "Expected the first parameter (the name of the operation to call) to be a symbol\n" \
|
30
|
+
"Actual: #{operation_name.inspect} (#{operation_name.class})"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(name, wsdl, globals)
|
35
|
+
@name = name
|
36
|
+
@wsdl = wsdl
|
37
|
+
@globals = globals
|
38
|
+
|
39
|
+
@logger = RequestLogger.new(globals)
|
40
|
+
end
|
41
|
+
|
42
|
+
def build(locals = {}, &block)
|
43
|
+
set_locals(locals, block)
|
44
|
+
Builder.new(@name, @wsdl, @globals, @locals)
|
45
|
+
end
|
46
|
+
|
47
|
+
def call(locals = {}, &block)
|
48
|
+
builder = build(locals, &block)
|
49
|
+
|
50
|
+
response = Savon.notify_observers(@name, builder, @globals, @locals)
|
51
|
+
response ||= call_with_logging build_request(builder)
|
52
|
+
|
53
|
+
raise_expected_httpi_response! unless response.kind_of?(HTTPI::Response)
|
54
|
+
|
55
|
+
create_response(response)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def create_response(response)
|
61
|
+
if multipart_supported?
|
62
|
+
Multipart::Response.new(response, @globals, @locals)
|
63
|
+
else
|
64
|
+
Response.new(response, @globals, @locals)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def multipart_supported?
|
69
|
+
return false unless @globals[:multipart] || @locals[:multipart]
|
70
|
+
|
71
|
+
if Savon.const_defined? :Multipart
|
72
|
+
true
|
73
|
+
else
|
74
|
+
raise 'Unable to find Savon::Multipart. Make sure the savon-multipart gem is installed and loaded.'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def set_locals(locals, block)
|
79
|
+
locals = LocalOptions.new(locals)
|
80
|
+
BlockInterface.new(locals).evaluate(block) if block
|
81
|
+
|
82
|
+
@locals = locals
|
83
|
+
end
|
84
|
+
|
85
|
+
def call_with_logging(request)
|
86
|
+
@logger.log(request) { HTTPI.post(request) }
|
87
|
+
end
|
88
|
+
|
89
|
+
def build_request(builder)
|
90
|
+
request = SOAPRequest.new(@globals).build(
|
91
|
+
:soap_action => soap_action,
|
92
|
+
:cookies => @locals[:cookies]
|
93
|
+
)
|
94
|
+
|
95
|
+
request.url = endpoint
|
96
|
+
request.body = builder.to_s
|
97
|
+
|
98
|
+
# TODO: could HTTPI do this automatically in case the header
|
99
|
+
# was not specified manually? [dh, 2013-01-04]
|
100
|
+
request.headers["Content-Length"] = request.body.bytesize.to_s
|
101
|
+
|
102
|
+
request
|
103
|
+
end
|
104
|
+
|
105
|
+
def soap_action
|
106
|
+
# soap_action explicitly set to something falsy
|
107
|
+
return if @locals.include?(:soap_action) && !@locals[:soap_action]
|
108
|
+
|
109
|
+
# get the soap_action from local options
|
110
|
+
soap_action = @locals[:soap_action]
|
111
|
+
# with no local option, but a wsdl, ask it for the soap_action
|
112
|
+
soap_action ||= @wsdl.soap_action(@name.to_sym) if @wsdl.document?
|
113
|
+
# if there is no soap_action up to this point, fallback to a simple default
|
114
|
+
soap_action ||= Gyoku.xml_tag(@name, :key_converter => @globals[:convert_request_keys_to])
|
115
|
+
end
|
116
|
+
|
117
|
+
def endpoint
|
118
|
+
@globals[:endpoint] || @wsdl.endpoint
|
119
|
+
end
|
120
|
+
|
121
|
+
def raise_expected_httpi_response!
|
122
|
+
raise Error, "Observers need to return an HTTPI::Response to mock " \
|
123
|
+
"the request or nil to execute the request."
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,330 @@
|
|
1
|
+
require "logger"
|
2
|
+
require "httpi"
|
3
|
+
|
4
|
+
module Savon
|
5
|
+
class Options
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@options = {}
|
9
|
+
assign options
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :option_type
|
13
|
+
|
14
|
+
def [](option)
|
15
|
+
@options[option]
|
16
|
+
end
|
17
|
+
|
18
|
+
def []=(option, value)
|
19
|
+
value = [value].flatten
|
20
|
+
self.send(option, *value)
|
21
|
+
end
|
22
|
+
|
23
|
+
def include?(option)
|
24
|
+
@options.key? option
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def assign(options)
|
30
|
+
options.each do |option, value|
|
31
|
+
self.send(option, value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def method_missing(option, _)
|
36
|
+
raise UnknownOptionError, "Unknown #{option_type} option: #{option.inspect}"
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
class GlobalOptions < Options
|
42
|
+
|
43
|
+
def initialize(options = {})
|
44
|
+
@option_type = :global
|
45
|
+
|
46
|
+
defaults = {
|
47
|
+
:encoding => "UTF-8",
|
48
|
+
:soap_version => 1,
|
49
|
+
:namespaces => {},
|
50
|
+
:logger => Logger.new($stdout),
|
51
|
+
:log => true,
|
52
|
+
:filters => [],
|
53
|
+
:pretty_print_xml => false,
|
54
|
+
:raise_errors => true,
|
55
|
+
:strip_namespaces => true,
|
56
|
+
:convert_response_tags_to => lambda { |tag| tag.snakecase.to_sym},
|
57
|
+
:multipart => false,
|
58
|
+
}
|
59
|
+
|
60
|
+
options = defaults.merge(options)
|
61
|
+
|
62
|
+
# this option is a shortcut on the logger which needs to be set
|
63
|
+
# before it can be modified to set the option.
|
64
|
+
delayed_level = options.delete(:log_level)
|
65
|
+
|
66
|
+
super(options)
|
67
|
+
|
68
|
+
log_level(delayed_level) unless delayed_level.nil?
|
69
|
+
end
|
70
|
+
|
71
|
+
# Location of the local or remote WSDL document.
|
72
|
+
def wsdl(wsdl_address)
|
73
|
+
@options[:wsdl] = wsdl_address
|
74
|
+
end
|
75
|
+
|
76
|
+
# SOAP endpoint.
|
77
|
+
def endpoint(endpoint)
|
78
|
+
@options[:endpoint] = endpoint
|
79
|
+
end
|
80
|
+
|
81
|
+
# Target namespace.
|
82
|
+
def namespace(namespace)
|
83
|
+
@options[:namespace] = namespace
|
84
|
+
end
|
85
|
+
|
86
|
+
# The namespace identifer.
|
87
|
+
def namespace_identifier(identifier)
|
88
|
+
@options[:namespace_identifier] = identifier
|
89
|
+
end
|
90
|
+
|
91
|
+
# Namespaces for the SOAP envelope.
|
92
|
+
def namespaces(namespaces)
|
93
|
+
@options[:namespaces] = namespaces
|
94
|
+
end
|
95
|
+
|
96
|
+
# Proxy server to use for all requests.
|
97
|
+
def proxy(proxy)
|
98
|
+
@options[:proxy] = proxy
|
99
|
+
end
|
100
|
+
|
101
|
+
# A Hash of HTTP headers.
|
102
|
+
def headers(headers)
|
103
|
+
@options[:headers] = headers
|
104
|
+
end
|
105
|
+
|
106
|
+
# Open timeout in seconds.
|
107
|
+
def open_timeout(open_timeout)
|
108
|
+
@options[:open_timeout] = open_timeout
|
109
|
+
end
|
110
|
+
|
111
|
+
# Read timeout in seconds.
|
112
|
+
def read_timeout(read_timeout)
|
113
|
+
@options[:read_timeout] = read_timeout
|
114
|
+
end
|
115
|
+
|
116
|
+
# The encoding to use. Defaults to "UTF-8".
|
117
|
+
def encoding(encoding)
|
118
|
+
@options[:encoding] = encoding
|
119
|
+
end
|
120
|
+
|
121
|
+
# The global SOAP header. Expected to be a Hash or responding to #to_s.
|
122
|
+
def soap_header(header)
|
123
|
+
@options[:soap_header] = header
|
124
|
+
end
|
125
|
+
|
126
|
+
# Sets whether elements should be :qualified or unqualified.
|
127
|
+
# If you need to use this option, please open an issue and make
|
128
|
+
# sure to add your WSDL document for debugging.
|
129
|
+
def element_form_default(element_form_default)
|
130
|
+
@options[:element_form_default] = element_form_default
|
131
|
+
end
|
132
|
+
|
133
|
+
# Can be used to change the SOAP envelope namespace identifier.
|
134
|
+
# If you need to use this option, please open an issue and make
|
135
|
+
# sure to add your WSDL document for debugging.
|
136
|
+
def env_namespace(env_namespace)
|
137
|
+
@options[:env_namespace] = env_namespace
|
138
|
+
end
|
139
|
+
|
140
|
+
# Changes the SOAP version to 1 or 2.
|
141
|
+
def soap_version(soap_version)
|
142
|
+
@options[:soap_version] = soap_version
|
143
|
+
end
|
144
|
+
|
145
|
+
# Whether or not to raise SOAP fault and HTTP errors.
|
146
|
+
def raise_errors(raise_errors)
|
147
|
+
@options[:raise_errors] = raise_errors
|
148
|
+
end
|
149
|
+
|
150
|
+
# Whether or not to log.
|
151
|
+
def log(log)
|
152
|
+
HTTPI.log = log
|
153
|
+
@options[:log] = log
|
154
|
+
end
|
155
|
+
|
156
|
+
# The logger to use. Defaults to a Savon::Logger instance.
|
157
|
+
def logger(logger)
|
158
|
+
@options[:logger] = logger
|
159
|
+
end
|
160
|
+
|
161
|
+
# Changes the Logger's log level.
|
162
|
+
def log_level(level)
|
163
|
+
levels = { :debug => 0, :info => 1, :warn => 2, :error => 3, :fatal => 4 }
|
164
|
+
|
165
|
+
unless levels.include? level
|
166
|
+
raise ArgumentError, "Invalid log level: #{level.inspect}\n" \
|
167
|
+
"Expected one of: #{levels.keys.inspect}"
|
168
|
+
end
|
169
|
+
|
170
|
+
@options[:logger].level = levels[level]
|
171
|
+
end
|
172
|
+
|
173
|
+
# A list of XML tags to filter from logged SOAP messages.
|
174
|
+
def filters(*filters)
|
175
|
+
@options[:filters] = filters.flatten
|
176
|
+
end
|
177
|
+
|
178
|
+
# Whether to pretty print request and response XML log messages.
|
179
|
+
def pretty_print_xml(pretty_print_xml)
|
180
|
+
@options[:pretty_print_xml] = pretty_print_xml
|
181
|
+
end
|
182
|
+
|
183
|
+
# Specifies the SSL version to use.
|
184
|
+
def ssl_version(version)
|
185
|
+
@options[:ssl_version] = version
|
186
|
+
end
|
187
|
+
|
188
|
+
# Whether and how to to verify the connection.
|
189
|
+
def ssl_verify_mode(verify_mode)
|
190
|
+
@options[:ssl_verify_mode] = verify_mode
|
191
|
+
end
|
192
|
+
|
193
|
+
# Sets the cert key file to use.
|
194
|
+
def ssl_cert_key_file(file)
|
195
|
+
@options[:ssl_cert_key_file] = file
|
196
|
+
end
|
197
|
+
|
198
|
+
# Sets the cert key password to use.
|
199
|
+
def ssl_cert_key_password(password)
|
200
|
+
@options[:ssl_cert_key_password] = password
|
201
|
+
end
|
202
|
+
|
203
|
+
# Sets the cert file to use.
|
204
|
+
def ssl_cert_file(file)
|
205
|
+
@options[:ssl_cert_file] = file
|
206
|
+
end
|
207
|
+
|
208
|
+
# Sets the ca cert file to use.
|
209
|
+
def ssl_ca_cert_file(file)
|
210
|
+
@options[:ssl_ca_cert_file] = file
|
211
|
+
end
|
212
|
+
|
213
|
+
# HTTP basic auth credentials.
|
214
|
+
def basic_auth(*credentials)
|
215
|
+
@options[:basic_auth] = credentials.flatten
|
216
|
+
end
|
217
|
+
|
218
|
+
# HTTP digest auth credentials.
|
219
|
+
def digest_auth(*credentials)
|
220
|
+
@options[:digest_auth] = credentials.flatten
|
221
|
+
end
|
222
|
+
|
223
|
+
# NTLM auth credentials.
|
224
|
+
def ntlm(*credentials)
|
225
|
+
@options[:ntlm] = credentials.flatten
|
226
|
+
end
|
227
|
+
|
228
|
+
# WSSE auth credentials for Akami.
|
229
|
+
def wsse_auth(*credentials)
|
230
|
+
@options[:wsse_auth] = credentials.flatten
|
231
|
+
end
|
232
|
+
|
233
|
+
# Instruct Akami to enable wsu:Timestamp headers.
|
234
|
+
def wsse_timestamp(*timestamp)
|
235
|
+
@options[:wsse_timestamp] = timestamp.flatten
|
236
|
+
end
|
237
|
+
|
238
|
+
# Instruct Nori whether to strip namespaces from XML nodes.
|
239
|
+
def strip_namespaces(strip_namespaces)
|
240
|
+
@options[:strip_namespaces] = strip_namespaces
|
241
|
+
end
|
242
|
+
|
243
|
+
# Tell Gyoku how to convert Hash key Symbols to XML tags.
|
244
|
+
# Accepts one of :lower_camelcase, :camelcase, :upcase, or :none.
|
245
|
+
def convert_request_keys_to(converter)
|
246
|
+
@options[:convert_request_keys_to] = converter
|
247
|
+
end
|
248
|
+
|
249
|
+
# Tell Nori how to convert XML tags from the SOAP response into Hash keys.
|
250
|
+
# Accepts a lambda or a block which receives an XML tag and returns a Hash key.
|
251
|
+
# Defaults to convert tags to snakecase Symbols.
|
252
|
+
def convert_response_tags_to(converter = nil, &block)
|
253
|
+
@options[:convert_response_tags_to] = block || converter
|
254
|
+
end
|
255
|
+
|
256
|
+
# Instruct Savon to create a multipart response if available.
|
257
|
+
def multipart(multipart)
|
258
|
+
@options[:multipart] = multipart
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
class LocalOptions < Options
|
263
|
+
|
264
|
+
def initialize(options = {})
|
265
|
+
@option_type = :local
|
266
|
+
|
267
|
+
defaults = {
|
268
|
+
:advanced_typecasting => true,
|
269
|
+
:response_parser => :nokogiri,
|
270
|
+
:multipart => false
|
271
|
+
}
|
272
|
+
|
273
|
+
super defaults.merge(options)
|
274
|
+
end
|
275
|
+
|
276
|
+
# The local SOAP header. Expected to be a Hash or respond to #to_s.
|
277
|
+
# Will be merged with the global SOAP header if both are Hashes.
|
278
|
+
# Otherwise the local option will be prefered.
|
279
|
+
def soap_header(header)
|
280
|
+
@options[:soap_header] = header
|
281
|
+
end
|
282
|
+
|
283
|
+
# The SOAP message to send. Expected to be a Hash or a String.
|
284
|
+
def message(message)
|
285
|
+
@options[:message] = message
|
286
|
+
end
|
287
|
+
|
288
|
+
# SOAP message tag (formerly known as SOAP input tag). If it's not set, Savon retrieves the name from
|
289
|
+
# the WSDL document (if available). Otherwise, Gyoku converts the operation name into an XML element.
|
290
|
+
def message_tag(message_tag)
|
291
|
+
@options[:message_tag] = message_tag
|
292
|
+
end
|
293
|
+
|
294
|
+
# Attributes for the SOAP message tag.
|
295
|
+
def attributes(attributes)
|
296
|
+
@options[:attributes] = attributes
|
297
|
+
end
|
298
|
+
|
299
|
+
# Value of the SOAPAction HTTP header.
|
300
|
+
def soap_action(soap_action)
|
301
|
+
@options[:soap_action] = soap_action
|
302
|
+
end
|
303
|
+
|
304
|
+
# Cookies to be used for the next request.
|
305
|
+
def cookies(cookies)
|
306
|
+
@options[:cookies] = cookies
|
307
|
+
end
|
308
|
+
|
309
|
+
# The SOAP request XML to send. Expected to be a String.
|
310
|
+
def xml(xml)
|
311
|
+
@options[:xml] = xml
|
312
|
+
end
|
313
|
+
|
314
|
+
# Instruct Nori to use advanced typecasting.
|
315
|
+
def advanced_typecasting(advanced)
|
316
|
+
@options[:advanced_typecasting] = advanced
|
317
|
+
end
|
318
|
+
|
319
|
+
# Instruct Nori to use :rexml or :nokogiri to parse the response.
|
320
|
+
def response_parser(parser)
|
321
|
+
@options[:response_parser] = parser
|
322
|
+
end
|
323
|
+
|
324
|
+
# Instruct Savon to create a multipart response if available.
|
325
|
+
def multipart(multipart)
|
326
|
+
@options[:multipart] = multipart
|
327
|
+
end
|
328
|
+
|
329
|
+
end
|
330
|
+
end
|