savon 1.2.0 → 2.0.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.
- data/CHANGELOG.md +119 -104
- data/README.md +12 -11
- data/Rakefile +0 -6
- data/lib/savon.rb +16 -14
- data/lib/savon/block_interface.rb +26 -0
- data/lib/savon/builder.rb +142 -0
- data/lib/savon/client.rb +36 -135
- data/lib/savon/header.rb +42 -0
- data/lib/savon/http_error.rb +27 -0
- data/lib/savon/log_message.rb +23 -25
- data/lib/savon/message.rb +35 -0
- data/lib/savon/mock.rb +5 -0
- data/lib/savon/mock/expectation.rb +70 -0
- data/lib/savon/mock/spec_helper.rb +62 -0
- data/lib/savon/model.rb +39 -61
- data/lib/savon/operation.rb +62 -0
- data/lib/savon/options.rb +265 -0
- data/lib/savon/qualified_message.rb +49 -0
- data/lib/savon/request.rb +92 -0
- data/lib/savon/response.rb +97 -0
- data/lib/savon/soap_fault.rb +40 -0
- data/lib/savon/version.rb +1 -1
- data/savon.gemspec +10 -8
- data/spec/integration/options_spec.rb +536 -0
- data/spec/integration/request_spec.rb +31 -16
- data/spec/integration/support/application.rb +80 -0
- data/spec/integration/support/server.rb +84 -0
- data/spec/savon/builder_spec.rb +81 -0
- data/spec/savon/client_spec.rb +90 -488
- data/spec/savon/http_error_spec.rb +49 -0
- data/spec/savon/log_message_spec.rb +33 -0
- data/spec/savon/mock_spec.rb +127 -0
- data/spec/savon/model_spec.rb +110 -99
- data/spec/savon/observers_spec.rb +92 -0
- data/spec/savon/operation_spec.rb +49 -0
- data/spec/savon/request_spec.rb +145 -0
- data/spec/savon/{soap/response_spec.rb → response_spec.rb} +22 -59
- data/spec/savon/soap_fault_spec.rb +94 -0
- data/spec/spec_helper.rb +5 -3
- data/spec/support/fixture.rb +5 -1
- metadata +202 -197
- data/lib/savon/config.rb +0 -46
- data/lib/savon/error.rb +0 -6
- data/lib/savon/hooks/group.rb +0 -68
- data/lib/savon/hooks/hook.rb +0 -61
- data/lib/savon/http/error.rb +0 -42
- data/lib/savon/logger.rb +0 -39
- data/lib/savon/null_logger.rb +0 -10
- data/lib/savon/soap.rb +0 -21
- data/lib/savon/soap/fault.rb +0 -59
- data/lib/savon/soap/invalid_response_error.rb +0 -13
- data/lib/savon/soap/request.rb +0 -86
- data/lib/savon/soap/request_builder.rb +0 -205
- data/lib/savon/soap/response.rb +0 -117
- data/lib/savon/soap/xml.rb +0 -257
- data/spec/savon/config_spec.rb +0 -38
- data/spec/savon/hooks/group_spec.rb +0 -71
- data/spec/savon/hooks/hook_spec.rb +0 -16
- data/spec/savon/http/error_spec.rb +0 -52
- data/spec/savon/logger_spec.rb +0 -51
- data/spec/savon/savon_spec.rb +0 -33
- data/spec/savon/soap/fault_spec.rb +0 -89
- data/spec/savon/soap/request_builder_spec.rb +0 -207
- data/spec/savon/soap/request_spec.rb +0 -112
- data/spec/savon/soap/xml_spec.rb +0 -357
- data/spec/savon/soap_spec.rb +0 -16
@@ -1,205 +0,0 @@
|
|
1
|
-
module Savon
|
2
|
-
module SOAP
|
3
|
-
|
4
|
-
# = Savon::SOAP::RequestBuilder
|
5
|
-
#
|
6
|
-
# Savon::SOAP::RequestBuilder builds Savon::SOAP::Request instances.
|
7
|
-
# The RequestBuilder is configured by the client that instantiates it.
|
8
|
-
# It uses the options set by the client to build an appropriate request.
|
9
|
-
class RequestBuilder
|
10
|
-
|
11
|
-
# Initialize a new +RequestBuilder+ with the given SOAP operation.
|
12
|
-
# The operation may be specified using a symbol or a string.
|
13
|
-
def initialize(operation, options = {})
|
14
|
-
@operation = operation
|
15
|
-
assign_options(options)
|
16
|
-
end
|
17
|
-
|
18
|
-
# Writer for the <tt>HTTPI::Request</tt> object.
|
19
|
-
attr_writer :http
|
20
|
-
|
21
|
-
# Writer for the <tt>Savon::SOAP::XML</tt> object.
|
22
|
-
attr_writer :soap
|
23
|
-
|
24
|
-
# Writer for the <tt>Akami::WSSE</tt> object.
|
25
|
-
attr_writer :wsse
|
26
|
-
|
27
|
-
# Writer for the <tt>Wasabi::Document</tt> object.
|
28
|
-
attr_writer :wsdl
|
29
|
-
|
30
|
-
# Writer for the <tt>Savon::Config</tt> object.
|
31
|
-
attr_writer :config
|
32
|
-
|
33
|
-
# Writer for the attributes of the SOAP input tag. Accepts a Hash.
|
34
|
-
attr_writer :attributes
|
35
|
-
|
36
|
-
# Writer for the namespace identifer of the <tt>Savon::SOAP::XML</tt>
|
37
|
-
# object.
|
38
|
-
attr_writer :namespace_identifier
|
39
|
-
|
40
|
-
# Writer for the SOAP action of the <tt>Savon::SOAP::XML</tt> object.
|
41
|
-
attr_writer :soap_action
|
42
|
-
|
43
|
-
# Reader for the operation of the request being built by the request builder.
|
44
|
-
attr_reader :operation
|
45
|
-
|
46
|
-
# Builds and returns a <tt>Savon::SOAP::Request</tt> object. You may optionally
|
47
|
-
# pass a block to the method that will be run after the initial configuration of
|
48
|
-
# the dependencies. +self+ will be yielded to the block if the block accepts an
|
49
|
-
# argument.
|
50
|
-
def request(&post_configuration_block)
|
51
|
-
configure_dependencies
|
52
|
-
|
53
|
-
if post_configuration_block
|
54
|
-
# Only yield self to the block if our block takes an argument
|
55
|
-
args = [] and (args << self if post_configuration_block.arity == 1)
|
56
|
-
post_configuration_block.call(*args)
|
57
|
-
end
|
58
|
-
|
59
|
-
Request.new(config, http, soap)
|
60
|
-
end
|
61
|
-
|
62
|
-
# Returns the identifier for the default namespace. If an operation namespace
|
63
|
-
# identifier is defined for the current operation in the WSDL document, this
|
64
|
-
# namespace identifier is used. Otherwise, the +@namespace_identifier+ instance
|
65
|
-
# variable is used.
|
66
|
-
def namespace_identifier
|
67
|
-
if operation_namespace_defined_in_wsdl?
|
68
|
-
wsdl.operations[operation][:namespace_identifier].to_sym
|
69
|
-
else
|
70
|
-
@namespace_identifier
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
# Returns the namespace identifier to be used for the the SOAP input tag.
|
75
|
-
# If +@namespace_identifier+ is not +nil+, it will be returned. Otherwise, the
|
76
|
-
# default namespace identifier as returned by +namespace_identifier+ will be
|
77
|
-
# returned.
|
78
|
-
def input_namespace_identifier
|
79
|
-
@namespace_identifier || namespace_identifier
|
80
|
-
end
|
81
|
-
|
82
|
-
# Returns the default namespace to be used for the SOAP request. If a namespace
|
83
|
-
# is defined for the operation in the WSDL document, this namespace will be
|
84
|
-
# returned. Otherwise, the default WSDL document namespace will be returned.
|
85
|
-
def namespace
|
86
|
-
if operation_namespace_defined_in_wsdl?
|
87
|
-
wsdl.parser.namespaces[namespace_identifier.to_s]
|
88
|
-
else
|
89
|
-
wsdl.namespace
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
# Returns true if the operation's namespace is defined within the WSDL
|
94
|
-
# document.
|
95
|
-
def operation_namespace_defined_in_wsdl?
|
96
|
-
return false unless wsdl.document?
|
97
|
-
(operation = wsdl.operations[self.operation]) && operation[:namespace_identifier]
|
98
|
-
end
|
99
|
-
|
100
|
-
# Returns the SOAP action. If +@soap_action+ has been defined, this will
|
101
|
-
# be returned. Otherwise, if there is a WSDL document defined, the SOAP
|
102
|
-
# action corresponding to the operation will be returned. Failing this,
|
103
|
-
# the operation name will be used to form the SOAP action.
|
104
|
-
def soap_action
|
105
|
-
return @soap_action if @soap_action
|
106
|
-
|
107
|
-
if wsdl.document?
|
108
|
-
wsdl.soap_action(operation.to_sym)
|
109
|
-
else
|
110
|
-
Gyoku::XMLKey.create(operation).to_sym
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
# Returns the SOAP operation input tag. If there is a WSDL document defined,
|
115
|
-
# and the operation's input tag is defined in the document, this will be
|
116
|
-
# returned. Otherwise, the operation name will be used to form the input tag.
|
117
|
-
def soap_input_tag
|
118
|
-
if wsdl.document? && (input = wsdl.soap_input(operation.to_sym))
|
119
|
-
input
|
120
|
-
else
|
121
|
-
Gyoku::XMLKey.create(operation)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
# Changes the body of the SOAP request to +body+.
|
126
|
-
def body=(body)
|
127
|
-
soap.body = body
|
128
|
-
end
|
129
|
-
|
130
|
-
# Returns the body of the SOAP request.
|
131
|
-
def body
|
132
|
-
soap.body
|
133
|
-
end
|
134
|
-
|
135
|
-
# Returns the attributes of the SOAP input tag. Defaults to
|
136
|
-
# an empty Hash.
|
137
|
-
def attributes
|
138
|
-
@attributes ||= {}
|
139
|
-
end
|
140
|
-
|
141
|
-
# Returns the <tt>Savon::Config</tt> object for the request. Defaults
|
142
|
-
# to a clone of <tt>Savon.config</tt>.
|
143
|
-
def config
|
144
|
-
@config ||= Savon.config.clone
|
145
|
-
end
|
146
|
-
|
147
|
-
# Returns the <tt>HTTPI::Request</tt> object.
|
148
|
-
def http
|
149
|
-
@http ||= HTTPI::Request.new
|
150
|
-
end
|
151
|
-
|
152
|
-
# Returns the <tt>SOAP::XML</tt> object.
|
153
|
-
def soap
|
154
|
-
@soap ||= XML.new(config)
|
155
|
-
end
|
156
|
-
|
157
|
-
# Returns the <tt>Wasabi::Document</tt> object.
|
158
|
-
def wsdl
|
159
|
-
@wsdl ||= Wasabi::Document.new
|
160
|
-
end
|
161
|
-
|
162
|
-
# Returns the <tt>Akami::WSSE</tt> object.
|
163
|
-
def wsse
|
164
|
-
@wsse ||= Akami.wsse
|
165
|
-
end
|
166
|
-
|
167
|
-
private
|
168
|
-
|
169
|
-
def configure_dependencies
|
170
|
-
soap.endpoint = wsdl.endpoint
|
171
|
-
soap.element_form_default = wsdl.element_form_default
|
172
|
-
soap.wsse = wsse
|
173
|
-
|
174
|
-
soap.namespace = namespace
|
175
|
-
soap.namespace_identifier = namespace_identifier
|
176
|
-
|
177
|
-
add_wsdl_namespaces_to_soap
|
178
|
-
add_wsdl_types_to_soap
|
179
|
-
|
180
|
-
soap.input = [input_namespace_identifier, soap_input_tag.to_sym, attributes]
|
181
|
-
|
182
|
-
http.headers["SOAPAction"] = %{"#{soap_action}"}
|
183
|
-
end
|
184
|
-
|
185
|
-
def add_wsdl_namespaces_to_soap
|
186
|
-
wsdl.type_namespaces.each do |path, uri|
|
187
|
-
soap.use_namespace(path, uri)
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
def add_wsdl_types_to_soap
|
192
|
-
wsdl.type_definitions.each do |path, type|
|
193
|
-
soap.types[path] = type
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
def assign_options(options)
|
198
|
-
options.each do |option, value|
|
199
|
-
send(:"#{option}=", value) if value
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
end
|
204
|
-
end
|
205
|
-
end
|
data/lib/savon/soap/response.rb
DELETED
@@ -1,117 +0,0 @@
|
|
1
|
-
require "savon/soap/xml"
|
2
|
-
require "savon/soap/fault"
|
3
|
-
require "savon/soap/invalid_response_error"
|
4
|
-
require "savon/http/error"
|
5
|
-
|
6
|
-
module Savon
|
7
|
-
module SOAP
|
8
|
-
|
9
|
-
# = Savon::SOAP::Response
|
10
|
-
#
|
11
|
-
# Represents the SOAP response and contains the HTTP response.
|
12
|
-
class Response
|
13
|
-
|
14
|
-
# Expects an <tt>HTTPI::Response</tt> and handles errors.
|
15
|
-
def initialize(config, response)
|
16
|
-
self.config = config
|
17
|
-
self.http = response
|
18
|
-
raise_errors if config.raise_errors
|
19
|
-
end
|
20
|
-
|
21
|
-
attr_accessor :http, :config
|
22
|
-
|
23
|
-
# Returns whether the request was successful.
|
24
|
-
def success?
|
25
|
-
!soap_fault? && !http_error?
|
26
|
-
end
|
27
|
-
|
28
|
-
# Returns whether there was a SOAP fault.
|
29
|
-
def soap_fault?
|
30
|
-
soap_fault.present?
|
31
|
-
end
|
32
|
-
|
33
|
-
# Returns the <tt>Savon::SOAP::Fault</tt>.
|
34
|
-
def soap_fault
|
35
|
-
@soap_fault ||= Fault.new http
|
36
|
-
end
|
37
|
-
|
38
|
-
# Returns whether there was an HTTP error.
|
39
|
-
def http_error?
|
40
|
-
http_error.present?
|
41
|
-
end
|
42
|
-
|
43
|
-
# Returns the <tt>Savon::HTTP::Error</tt>.
|
44
|
-
def http_error
|
45
|
-
@http_error ||= HTTP::Error.new http
|
46
|
-
end
|
47
|
-
|
48
|
-
# Shortcut accessor for the SOAP response body Hash.
|
49
|
-
def [](key)
|
50
|
-
body[key]
|
51
|
-
end
|
52
|
-
|
53
|
-
# Returns the SOAP response header as a Hash.
|
54
|
-
def header
|
55
|
-
if !hash.has_key? :envelope
|
56
|
-
raise Savon::SOAP::InvalidResponseError, "Unable to parse response body '#{to_xml}'"
|
57
|
-
end
|
58
|
-
hash[:envelope][:header]
|
59
|
-
end
|
60
|
-
|
61
|
-
# Returns the SOAP response body as a Hash.
|
62
|
-
def body
|
63
|
-
if !hash.has_key? :envelope
|
64
|
-
raise Savon::SOAP::InvalidResponseError, "Unable to parse response body '#{to_xml}'"
|
65
|
-
end
|
66
|
-
hash[:envelope][:body]
|
67
|
-
end
|
68
|
-
|
69
|
-
alias to_hash body
|
70
|
-
|
71
|
-
# Traverses the SOAP response body Hash for a given +path+ of Hash keys and returns
|
72
|
-
# the value as an Array. Defaults to return an empty Array in case the path does not
|
73
|
-
# exist or returns nil.
|
74
|
-
def to_array(*path)
|
75
|
-
result = path.inject body do |memo, key|
|
76
|
-
return [] unless memo[key]
|
77
|
-
memo[key]
|
78
|
-
end
|
79
|
-
|
80
|
-
result.kind_of?(Array) ? result.compact : [result].compact
|
81
|
-
end
|
82
|
-
|
83
|
-
# Returns the complete SOAP response XML without normalization.
|
84
|
-
def hash
|
85
|
-
@hash ||= Nori.parse(to_xml)
|
86
|
-
end
|
87
|
-
|
88
|
-
# Returns the SOAP response XML.
|
89
|
-
def to_xml
|
90
|
-
http.body
|
91
|
-
end
|
92
|
-
|
93
|
-
# Returns a <tt>Nokogiri::XML::Document</tt> for the SOAP response XML.
|
94
|
-
def doc
|
95
|
-
@doc ||= Nokogiri::XML(to_xml)
|
96
|
-
end
|
97
|
-
|
98
|
-
# Returns an Array of <tt>Nokogiri::XML::Node</tt> objects retrieved with the given +path+.
|
99
|
-
# Automatically adds all of the document's namespaces unless a +namespaces+ hash is provided.
|
100
|
-
def xpath(path, namespaces = nil)
|
101
|
-
doc.xpath(path, namespaces || xml_namespaces)
|
102
|
-
end
|
103
|
-
|
104
|
-
private
|
105
|
-
|
106
|
-
def raise_errors
|
107
|
-
raise soap_fault if soap_fault?
|
108
|
-
raise http_error if http_error?
|
109
|
-
end
|
110
|
-
|
111
|
-
def xml_namespaces
|
112
|
-
@xml_namespaces ||= doc.collect_namespaces
|
113
|
-
end
|
114
|
-
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
data/lib/savon/soap/xml.rb
DELETED
@@ -1,257 +0,0 @@
|
|
1
|
-
require "builder"
|
2
|
-
require "gyoku"
|
3
|
-
require "rexml/document"
|
4
|
-
require "nori"
|
5
|
-
|
6
|
-
require "savon/soap"
|
7
|
-
|
8
|
-
Nori.configure do |config|
|
9
|
-
config.strip_namespaces = true
|
10
|
-
config.convert_tags_to { |tag| tag.snakecase.to_sym }
|
11
|
-
end
|
12
|
-
|
13
|
-
module Savon
|
14
|
-
module SOAP
|
15
|
-
|
16
|
-
# = Savon::SOAP::XML
|
17
|
-
#
|
18
|
-
# Represents the SOAP request XML. Contains various global and per request/instance settings
|
19
|
-
# like the SOAP version, header, body and namespaces.
|
20
|
-
class XML
|
21
|
-
|
22
|
-
# XML Schema Type namespaces.
|
23
|
-
SCHEMA_TYPES = {
|
24
|
-
"xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
|
25
|
-
"xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance"
|
26
|
-
}
|
27
|
-
|
28
|
-
# Expects a +config+ object.
|
29
|
-
def initialize(config)
|
30
|
-
self.config = config
|
31
|
-
end
|
32
|
-
|
33
|
-
attr_accessor :config
|
34
|
-
|
35
|
-
# Accessor for the SOAP +input+ tag.
|
36
|
-
attr_accessor :input
|
37
|
-
|
38
|
-
# Accessor for the SOAP +endpoint+.
|
39
|
-
attr_accessor :endpoint
|
40
|
-
|
41
|
-
# Sets the SOAP +version+.
|
42
|
-
def version=(version)
|
43
|
-
raise ArgumentError, "Invalid SOAP version: #{version}" unless SOAP::VERSIONS.include? version
|
44
|
-
@version = version
|
45
|
-
end
|
46
|
-
|
47
|
-
# Returns the SOAP +version+. Defaults to <tt>Savon.config.soap_version</tt>.
|
48
|
-
def version
|
49
|
-
@version ||= config.soap_version
|
50
|
-
end
|
51
|
-
|
52
|
-
# Sets the SOAP +header+ Hash.
|
53
|
-
attr_writer :header
|
54
|
-
|
55
|
-
# Returns the SOAP +header+. Defaults to an empty Hash.
|
56
|
-
def header
|
57
|
-
@header ||= config.soap_header.nil? ? {} : config.soap_header
|
58
|
-
end
|
59
|
-
|
60
|
-
# Sets the SOAP envelope namespace.
|
61
|
-
attr_writer :env_namespace
|
62
|
-
|
63
|
-
# Returns the SOAP envelope namespace. Uses the global namespace if set Defaults to :env.
|
64
|
-
def env_namespace
|
65
|
-
@env_namespace ||= config.env_namespace.nil? ? :env : config.env_namespace
|
66
|
-
end
|
67
|
-
|
68
|
-
# Sets the +namespaces+ Hash.
|
69
|
-
attr_writer :namespaces
|
70
|
-
|
71
|
-
# Returns the +namespaces+. Defaults to a Hash containing the SOAP envelope namespace.
|
72
|
-
def namespaces
|
73
|
-
@namespaces ||= begin
|
74
|
-
key = ["xmlns"]
|
75
|
-
key << env_namespace if env_namespace && env_namespace != ""
|
76
|
-
{ key.join(":") => SOAP::NAMESPACE[version] }
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def namespace_by_uri(uri)
|
81
|
-
namespaces.each do |candidate_identifier, candidate_uri|
|
82
|
-
return candidate_identifier.gsub(/^xmlns:/, '') if candidate_uri == uri
|
83
|
-
end
|
84
|
-
nil
|
85
|
-
end
|
86
|
-
|
87
|
-
def used_namespaces
|
88
|
-
@used_namespaces ||= {}
|
89
|
-
end
|
90
|
-
|
91
|
-
def use_namespace(path, uri)
|
92
|
-
@internal_namespace_count ||= 0
|
93
|
-
|
94
|
-
unless identifier = namespace_by_uri(uri)
|
95
|
-
identifier = "ins#{@internal_namespace_count}"
|
96
|
-
namespaces["xmlns:#{identifier}"] = uri
|
97
|
-
@internal_namespace_count += 1
|
98
|
-
end
|
99
|
-
|
100
|
-
used_namespaces[path] = identifier
|
101
|
-
end
|
102
|
-
|
103
|
-
def types
|
104
|
-
@types ||= {}
|
105
|
-
end
|
106
|
-
|
107
|
-
# Sets the default namespace identifier.
|
108
|
-
attr_writer :namespace_identifier
|
109
|
-
|
110
|
-
# Returns the default namespace identifier.
|
111
|
-
def namespace_identifier
|
112
|
-
@namespace_identifier ||= :wsdl
|
113
|
-
end
|
114
|
-
|
115
|
-
# Accessor for whether all local elements should be namespaced.
|
116
|
-
attr_accessor :element_form_default
|
117
|
-
|
118
|
-
# Accessor for the default namespace URI.
|
119
|
-
attr_accessor :namespace
|
120
|
-
|
121
|
-
# Accessor for the <tt>Savon::WSSE</tt> object.
|
122
|
-
attr_accessor :wsse
|
123
|
-
|
124
|
-
def signature?
|
125
|
-
wsse.respond_to?(:signature?) && wsse.signature?
|
126
|
-
end
|
127
|
-
|
128
|
-
# Returns the SOAP request encoding. Defaults to "UTF-8".
|
129
|
-
def encoding
|
130
|
-
@encoding ||= "UTF-8"
|
131
|
-
end
|
132
|
-
|
133
|
-
# Sets the SOAP request encoding.
|
134
|
-
attr_writer :encoding
|
135
|
-
|
136
|
-
# Accepts a +block+ and yields a <tt>Builder::XmlMarkup</tt> object to let you create
|
137
|
-
# custom body XML.
|
138
|
-
def body
|
139
|
-
@body = yield builder(nil) if block_given?
|
140
|
-
@body
|
141
|
-
end
|
142
|
-
|
143
|
-
# Sets the SOAP +body+. Expected to be a Hash that can be translated to XML via `Gyoku.xml`
|
144
|
-
# or any other Object responding to to_s.
|
145
|
-
attr_writer :body
|
146
|
-
|
147
|
-
# Accepts a +block+ and yields a <tt>Builder::XmlMarkup</tt> object to let you create
|
148
|
-
# a completely custom XML.
|
149
|
-
def xml(directive_tag = :xml, attrs = {})
|
150
|
-
@xml = yield builder(directive_tag, attrs) if block_given?
|
151
|
-
end
|
152
|
-
|
153
|
-
# Accepts an XML String and lets you specify a completely custom request body.
|
154
|
-
attr_writer :xml
|
155
|
-
|
156
|
-
# Returns the XML for a SOAP request.
|
157
|
-
def to_xml(clear_cache = false)
|
158
|
-
if clear_cache
|
159
|
-
@xml = nil
|
160
|
-
@header_for_xml = nil
|
161
|
-
end
|
162
|
-
|
163
|
-
@xml ||= tag(builder, :Envelope, complete_namespaces) do |xml|
|
164
|
-
tag(xml, :Header) { xml << header_for_xml } unless header_for_xml.empty?
|
165
|
-
|
166
|
-
# TODO: Maybe there should be some sort of plugin architecture where
|
167
|
-
# classes like WSSE::Signature can hook into this process.
|
168
|
-
body_attributes = (signature? ? wsse.signature.body_attributes : {})
|
169
|
-
|
170
|
-
if input.nil?
|
171
|
-
tag(xml, :Body, body_attributes)
|
172
|
-
else
|
173
|
-
tag(xml, :Body, body_attributes) { xml.tag!(*add_namespace_to_input) { xml << body_to_xml } }
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
private
|
179
|
-
|
180
|
-
# Returns a new <tt>Builder::XmlMarkup</tt> object.
|
181
|
-
def builder(directive_tag = :xml, attrs = { :encoding => encoding })
|
182
|
-
builder = Builder::XmlMarkup.new
|
183
|
-
builder.instruct!(directive_tag, attrs) if directive_tag
|
184
|
-
builder
|
185
|
-
end
|
186
|
-
|
187
|
-
# Expects a builder +xml+ instance, a tag +name+ and accepts optional +namespaces+
|
188
|
-
# and a block to create an XML tag.
|
189
|
-
def tag(xml, name, namespaces = {}, &block)
|
190
|
-
if env_namespace && env_namespace != ""
|
191
|
-
xml.tag! env_namespace, name, namespaces, &block
|
192
|
-
else
|
193
|
-
xml.tag! name, namespaces, &block
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
# Returns the complete Hash of namespaces.
|
198
|
-
def complete_namespaces
|
199
|
-
defaults = SCHEMA_TYPES.dup
|
200
|
-
defaults["xmlns:#{namespace_identifier}"] = namespace if namespace
|
201
|
-
defaults.merge namespaces
|
202
|
-
end
|
203
|
-
|
204
|
-
# Returns the SOAP header as an XML String.
|
205
|
-
def header_for_xml
|
206
|
-
@header_for_xml ||= (Hash === header ? Gyoku.xml(header) : header) + wsse_header
|
207
|
-
end
|
208
|
-
|
209
|
-
# Returns the WSSE header or an empty String in case WSSE was not set.
|
210
|
-
def wsse_header
|
211
|
-
wsse.respond_to?(:to_xml) ? wsse.to_xml : ""
|
212
|
-
end
|
213
|
-
|
214
|
-
# Returns the SOAP body as an XML String.
|
215
|
-
def body_to_xml
|
216
|
-
return body.to_s unless body.kind_of? Hash
|
217
|
-
body_to_xml = element_form_default == :qualified ? add_namespaces_to_body(body) : body
|
218
|
-
Gyoku.xml body_to_xml, :element_form_default => element_form_default, :namespace => namespace_identifier
|
219
|
-
end
|
220
|
-
|
221
|
-
def add_namespaces_to_body(hash, path = [input[1].to_s])
|
222
|
-
return unless hash
|
223
|
-
return hash.map { |value| add_namespaces_to_body(value, path) } if hash.kind_of?(Array)
|
224
|
-
return hash.to_s unless hash.kind_of? Hash
|
225
|
-
|
226
|
-
hash.inject({}) do |newhash, (key, value)|
|
227
|
-
camelcased_key = Gyoku::XMLKey.create(key)
|
228
|
-
newpath = path + [camelcased_key]
|
229
|
-
|
230
|
-
if used_namespaces[newpath]
|
231
|
-
newhash.merge(
|
232
|
-
"#{used_namespaces[newpath]}:#{camelcased_key}" =>
|
233
|
-
add_namespaces_to_body(value, types[newpath] ? [types[newpath]] : newpath)
|
234
|
-
)
|
235
|
-
else
|
236
|
-
add_namespaces_to_values(value, path) if key == :order!
|
237
|
-
newhash.merge(key => value)
|
238
|
-
end
|
239
|
-
end
|
240
|
-
end
|
241
|
-
|
242
|
-
def add_namespace_to_input
|
243
|
-
return input.compact unless used_namespaces[[input[1].to_s]]
|
244
|
-
[used_namespaces[[input[1].to_s]], input[1], input[2]]
|
245
|
-
end
|
246
|
-
|
247
|
-
def add_namespaces_to_values(values, path)
|
248
|
-
values.collect! { |value|
|
249
|
-
camelcased_value = Gyoku::XMLKey.create(value)
|
250
|
-
namespace_path = path + [camelcased_value.to_s]
|
251
|
-
namespace = used_namespaces[namespace_path]
|
252
|
-
"#{namespace.blank? ? '' : namespace + ":"}#{camelcased_value}"
|
253
|
-
}
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
257
|
-
end
|