julianmorrison-savon 0.6.8
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 +92 -0
- data/README.textile +71 -0
- data/Rakefile +27 -0
- data/lib/savon.rb +34 -0
- data/lib/savon/client.rb +84 -0
- data/lib/savon/core_ext.rb +3 -0
- data/lib/savon/core_ext/datetime.rb +8 -0
- data/lib/savon/core_ext/hash.rb +78 -0
- data/lib/savon/core_ext/object.rb +21 -0
- data/lib/savon/core_ext/string.rb +47 -0
- data/lib/savon/core_ext/symbol.rb +8 -0
- data/lib/savon/core_ext/uri.rb +10 -0
- data/lib/savon/request.rb +159 -0
- data/lib/savon/response.rb +108 -0
- data/lib/savon/soap.rb +138 -0
- data/lib/savon/wsdl.rb +122 -0
- data/lib/savon/wsse.rb +122 -0
- data/spec/endpoint_helper.rb +22 -0
- data/spec/fixtures/response/response_fixture.rb +32 -0
- data/spec/fixtures/response/xml/authentication.xml +14 -0
- data/spec/fixtures/response/xml/soap_fault.xml +8 -0
- data/spec/fixtures/response/xml/soap_fault12.xml +18 -0
- data/spec/fixtures/wsdl/wsdl_fixture.rb +37 -0
- data/spec/fixtures/wsdl/xml/authentication.xml +63 -0
- data/spec/fixtures/wsdl/xml/namespaced_actions.xml +307 -0
- data/spec/fixtures/wsdl/xml/no_namespace.xml +115 -0
- data/spec/http_stubs.rb +23 -0
- data/spec/savon/client_spec.rb +83 -0
- data/spec/savon/core_ext/datetime_spec.rb +12 -0
- data/spec/savon/core_ext/hash_spec.rb +134 -0
- data/spec/savon/core_ext/object_spec.rb +40 -0
- data/spec/savon/core_ext/string_spec.rb +68 -0
- data/spec/savon/core_ext/symbol_spec.rb +11 -0
- data/spec/savon/core_ext/uri_spec.rb +15 -0
- data/spec/savon/request_spec.rb +124 -0
- data/spec/savon/response_spec.rb +122 -0
- data/spec/savon/savon_spec.rb +23 -0
- data/spec/savon/soap_spec.rb +131 -0
- data/spec/savon/wsdl_spec.rb +84 -0
- data/spec/savon/wsse_spec.rb +132 -0
- data/spec/spec_helper.rb +16 -0
- metadata +166 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
module Savon
|
2
|
+
|
3
|
+
# == Savon::Request
|
4
|
+
#
|
5
|
+
# Handles both WSDL and SOAP HTTP requests.
|
6
|
+
class Request
|
7
|
+
|
8
|
+
# Content-Types by SOAP version.
|
9
|
+
ContentType = { 1 => "text/xml", 2 => "application/soap+xml" }
|
10
|
+
|
11
|
+
# Whether to log HTTP requests.
|
12
|
+
@@log = true
|
13
|
+
|
14
|
+
# The default logger.
|
15
|
+
@@logger = Logger.new STDOUT
|
16
|
+
|
17
|
+
# The default log level.
|
18
|
+
@@log_level = :debug
|
19
|
+
|
20
|
+
# Sets whether to log HTTP requests.
|
21
|
+
def self.log=(log)
|
22
|
+
@@log = log
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns whether to log HTTP requests.
|
26
|
+
def self.log?
|
27
|
+
@@log
|
28
|
+
end
|
29
|
+
|
30
|
+
# Sets the logger.
|
31
|
+
def self.logger=(logger)
|
32
|
+
@@logger = logger
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the logger.
|
36
|
+
def self.logger
|
37
|
+
@@logger
|
38
|
+
end
|
39
|
+
|
40
|
+
# Sets the log level.
|
41
|
+
def self.log_level=(log_level)
|
42
|
+
@@log_level = log_level
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns the log level.
|
46
|
+
def self.log_level
|
47
|
+
@@log_level
|
48
|
+
end
|
49
|
+
|
50
|
+
# Expects a SOAP +endpoint+ String. Also accepts an optional Hash of
|
51
|
+
# +options+ for specifying a proxy server and SSL client authentication.
|
52
|
+
def initialize(endpoint, options = {})
|
53
|
+
@endpoint = URI endpoint
|
54
|
+
@proxy = options[:proxy] ? URI(options[:proxy]) : URI("")
|
55
|
+
@ssl = options[:ssl] if options[:ssl]
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns the endpoint URI.
|
59
|
+
attr_reader :endpoint
|
60
|
+
|
61
|
+
# Returns the proxy URI.
|
62
|
+
attr_reader :proxy
|
63
|
+
|
64
|
+
# Accessor for HTTP open timeout.
|
65
|
+
attr_accessor :open_timeout
|
66
|
+
|
67
|
+
# Accessor for HTTP read timeout.
|
68
|
+
attr_accessor :read_timeout
|
69
|
+
|
70
|
+
# Retrieves WSDL document and returns the Net::HTTPResponse.
|
71
|
+
def wsdl
|
72
|
+
log "Retrieving WSDL from: #{@endpoint}"
|
73
|
+
|
74
|
+
query = @endpoint.path
|
75
|
+
query += ('?' + @endpoint.query) if @endpoint.query
|
76
|
+
req = Net::HTTP::Get.new query
|
77
|
+
req.basic_auth(@endpoint.user, @endpoint.password) if @endpoint.user
|
78
|
+
|
79
|
+
http.start {|h| h.request(req) }
|
80
|
+
end
|
81
|
+
|
82
|
+
# Executes a SOAP request using a given Savon::SOAP instance and
|
83
|
+
# returns the Net::HTTPResponse.
|
84
|
+
def soap(soap)
|
85
|
+
@soap = soap
|
86
|
+
|
87
|
+
log_request
|
88
|
+
|
89
|
+
req = Net::HTTP::Post.new @soap.endpoint.path, http_header
|
90
|
+
req.body = @soap.to_xml
|
91
|
+
req.basic_auth(@soap.endpoint.user, @soap.endpoint.password) if @soap.endpoint.user
|
92
|
+
|
93
|
+
@response = http(@soap.endpoint).start {|h| h.request(req) }
|
94
|
+
|
95
|
+
log_response
|
96
|
+
@response
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
# Logs the SOAP request.
|
102
|
+
def log_request
|
103
|
+
log "SOAP request: #{@soap.endpoint}"
|
104
|
+
log http_header.map { |key, value| "#{key}: #{value}" }.join( ", " )
|
105
|
+
log @soap.to_xml
|
106
|
+
end
|
107
|
+
|
108
|
+
# Logs the SOAP response.
|
109
|
+
def log_response
|
110
|
+
log "SOAP response (status #{@response.code}):"
|
111
|
+
log @response.body
|
112
|
+
end
|
113
|
+
|
114
|
+
# Returns a Net::HTTP instance for a given +endpoint+.
|
115
|
+
def http(endpoint = @endpoint)
|
116
|
+
@http = Net::HTTP::Proxy(@proxy.host, @proxy.port).new endpoint.host, endpoint.port
|
117
|
+
set_http_timeout
|
118
|
+
set_ssl_options endpoint.ssl?
|
119
|
+
set_ssl_authentication if @ssl
|
120
|
+
@http
|
121
|
+
end
|
122
|
+
|
123
|
+
# Sets HTTP open and read timeout.
|
124
|
+
def set_http_timeout
|
125
|
+
@http.open_timeout = @open_timeout if @open_timeout
|
126
|
+
@http.read_timeout = @read_timeout if @read_timeout
|
127
|
+
end
|
128
|
+
|
129
|
+
# Sets basic SSL options to the +@http+ instance.
|
130
|
+
def set_ssl_options(use_ssl)
|
131
|
+
@http.use_ssl = use_ssl
|
132
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
133
|
+
end
|
134
|
+
|
135
|
+
# Sets SSL client authentication to the +@http+ instance.
|
136
|
+
def set_ssl_authentication
|
137
|
+
@http.verify_mode = @ssl[:verify] if @ssl[:verify].kind_of? Integer
|
138
|
+
@http.cert = @ssl[:client_cert] if @ssl[:client_cert]
|
139
|
+
@http.key = @ssl[:client_key] if @ssl[:client_key]
|
140
|
+
@http.ca_file = @ssl[:ca_file] if @ssl[:ca_file]
|
141
|
+
end
|
142
|
+
|
143
|
+
# Returns a Hash containing the header for an HTTP request.
|
144
|
+
def http_header
|
145
|
+
{ "Content-Type" => ContentType[@soap.version], "SOAPAction" => @soap.action }
|
146
|
+
end
|
147
|
+
|
148
|
+
# Logs a given +message+.
|
149
|
+
def log(message)
|
150
|
+
self.class.logger.send self.class.log_level, message if log?
|
151
|
+
end
|
152
|
+
|
153
|
+
# Returns whether logging is possible.
|
154
|
+
def log?
|
155
|
+
self.class.log? && self.class.logger.respond_to?(self.class.log_level)
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Savon
|
2
|
+
|
3
|
+
# == Savon::Response
|
4
|
+
#
|
5
|
+
# Represents the HTTP and SOAP response.
|
6
|
+
class Response
|
7
|
+
|
8
|
+
# The global setting of whether to raise errors.
|
9
|
+
@@raise_errors = true
|
10
|
+
|
11
|
+
# Sets the global setting of whether to raise errors.
|
12
|
+
def self.raise_errors=(raise_errors)
|
13
|
+
@@raise_errors = raise_errors
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the global setting of whether to raise errors.
|
17
|
+
def self.raise_errors?
|
18
|
+
@@raise_errors
|
19
|
+
end
|
20
|
+
|
21
|
+
# Expects a Net::HTTPResponse and handles errors.
|
22
|
+
def initialize(response)
|
23
|
+
@response = response
|
24
|
+
|
25
|
+
handle_soap_fault
|
26
|
+
handle_http_error
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns whether there was a SOAP fault.
|
30
|
+
def soap_fault?
|
31
|
+
@soap_fault
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the SOAP fault message.
|
35
|
+
attr_reader :soap_fault
|
36
|
+
|
37
|
+
# Returns whether there was an HTTP error.
|
38
|
+
def http_error?
|
39
|
+
@http_error
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns the HTTP error message.
|
43
|
+
attr_reader :http_error
|
44
|
+
|
45
|
+
# Returns the SOAP response as a Hash.
|
46
|
+
def to_hash
|
47
|
+
@body.find_regexp(/.+/).map_soap_response
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns the SOAP response XML.
|
51
|
+
def to_xml
|
52
|
+
@response.body
|
53
|
+
end
|
54
|
+
|
55
|
+
alias :to_s :to_xml
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
# Returns the SOAP response body as a Hash.
|
60
|
+
def body
|
61
|
+
unless @body
|
62
|
+
body = Crack::XML.parse @response.body
|
63
|
+
@body = body.find_regexp [/.+:Envelope/, /.+:Body/]
|
64
|
+
end
|
65
|
+
@body
|
66
|
+
end
|
67
|
+
|
68
|
+
# Handles SOAP faults. Raises a Savon::SOAPFault unless the default
|
69
|
+
# behavior of raising errors was turned off.
|
70
|
+
def handle_soap_fault
|
71
|
+
if soap_fault_message
|
72
|
+
@soap_fault = soap_fault_message
|
73
|
+
raise Savon::SOAPFault, soap_fault_message if self.class.raise_errors?
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns a SOAP fault message in case a SOAP fault was found.
|
78
|
+
def soap_fault_message
|
79
|
+
unless @soap_fault_message
|
80
|
+
soap_fault = body.find_regexp [/.+:Fault/]
|
81
|
+
@soap_fault_message = soap_fault_message_by_version(soap_fault)
|
82
|
+
end
|
83
|
+
@soap_fault_message
|
84
|
+
end
|
85
|
+
|
86
|
+
# Expects a Hash that might contain information about a SOAP fault.
|
87
|
+
# Returns the SOAP fault message in case one was found.
|
88
|
+
def soap_fault_message_by_version(soap_fault)
|
89
|
+
if soap_fault.keys.include? "faultcode"
|
90
|
+
"(#{soap_fault['faultcode']}) #{soap_fault['faultstring']}"
|
91
|
+
elsif soap_fault.keys.include? "Code"
|
92
|
+
# SOAP 1.2 error code element is capitalized, see: http://www.w3.org/TR/soap12-part1/#faultcodeelement
|
93
|
+
"(#{soap_fault['Code']['Value']}) #{soap_fault['Reason']['Text']}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Handles HTTP errors. Raises a Savon::HTTPError unless the default
|
98
|
+
# behavior of raising errors was turned off.
|
99
|
+
def handle_http_error
|
100
|
+
if @response.code.to_i >= 300
|
101
|
+
@http_error = "#{@response.message} (#{@response.code})"
|
102
|
+
@http_error << ": #{@response.body}" unless @response.body.empty?
|
103
|
+
raise Savon::HTTPError, http_error if self.class.raise_errors?
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
data/lib/savon/soap.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
module Savon
|
2
|
+
|
3
|
+
# == Savon::SOAP
|
4
|
+
#
|
5
|
+
# Represents the SOAP parameters and envelope.
|
6
|
+
class SOAP
|
7
|
+
|
8
|
+
# SOAP namespaces by SOAP version.
|
9
|
+
SOAPNamespace = {
|
10
|
+
1 => "http://schemas.xmlsoap.org/soap/envelope/",
|
11
|
+
2 => "http://www.w3.org/2003/05/soap-envelope"
|
12
|
+
}
|
13
|
+
|
14
|
+
# Content-Types by SOAP version.
|
15
|
+
ContentType = { 1 => "text/xml", 2 => "application/soap+xml" }
|
16
|
+
|
17
|
+
# The global SOAP version.
|
18
|
+
@@version = 1
|
19
|
+
|
20
|
+
# Returns the global SOAP version.
|
21
|
+
def self.version
|
22
|
+
@@version
|
23
|
+
end
|
24
|
+
|
25
|
+
# Sets the global SOAP version.
|
26
|
+
def self.version=(version)
|
27
|
+
@@version = version if Savon::SOAPVersions.include? version
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
@builder = Builder::XmlMarkup.new
|
32
|
+
end
|
33
|
+
|
34
|
+
# Sets the WSSE options.
|
35
|
+
attr_writer :wsse
|
36
|
+
|
37
|
+
# Sets the SOAP action.
|
38
|
+
attr_writer :action
|
39
|
+
|
40
|
+
# Returns the SOAP action.
|
41
|
+
def action
|
42
|
+
@action ||= ""
|
43
|
+
end
|
44
|
+
|
45
|
+
# Sets the SOAP input.
|
46
|
+
attr_writer :input
|
47
|
+
|
48
|
+
# Returns the SOAP input.
|
49
|
+
def input
|
50
|
+
@input ||= ""
|
51
|
+
end
|
52
|
+
|
53
|
+
# Accessor for the SOAP endpoint.
|
54
|
+
attr_accessor :endpoint
|
55
|
+
|
56
|
+
# Sets the SOAP header. Expected to be a Hash that can be translated
|
57
|
+
# to XML via Hash.to_soap_xml or any other Object responding to to_s.
|
58
|
+
attr_writer :header
|
59
|
+
|
60
|
+
# Returns the SOAP header. Defaults to an empty Hash.
|
61
|
+
def header
|
62
|
+
@header ||= {}
|
63
|
+
end
|
64
|
+
|
65
|
+
# Sets the SOAP body. Expected to be a Hash that can be translated to
|
66
|
+
# XML via Hash.to_soap_xml or any other Object responding to to_s.
|
67
|
+
attr_writer :body
|
68
|
+
|
69
|
+
# Sets the namespaces. Expected to be a Hash containing the namespaces
|
70
|
+
# (keys) and the corresponding URI's (values).
|
71
|
+
attr_writer :namespaces
|
72
|
+
|
73
|
+
# Returns the namespaces. A Hash containing the namespaces (keys) and
|
74
|
+
# the corresponding URI's (values).
|
75
|
+
def namespaces
|
76
|
+
@namespaces ||= { "xmlns:env" => SOAPNamespace[version] }
|
77
|
+
end
|
78
|
+
|
79
|
+
# Convenience method for setting the "xmlns:wsdl" namespace.
|
80
|
+
def namespace=(namespace)
|
81
|
+
namespaces["xmlns:wsdl"] = namespace
|
82
|
+
end
|
83
|
+
|
84
|
+
# Sets the SOAP version.
|
85
|
+
def version=(version)
|
86
|
+
@version = version if Savon::SOAPVersions.include? version
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns the SOAP version. Defaults to the global default.
|
90
|
+
def version
|
91
|
+
@version ||= self.class.version
|
92
|
+
end
|
93
|
+
|
94
|
+
# Returns the SOAP envelope XML.
|
95
|
+
def to_xml
|
96
|
+
unless @xml_body
|
97
|
+
@xml_body = @builder.env :Envelope, namespaces do |xml|
|
98
|
+
xml_header xml
|
99
|
+
xml_body xml
|
100
|
+
end
|
101
|
+
end
|
102
|
+
@xml_body
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
# Adds a SOAP XML header to a given +xml+ Object.
|
108
|
+
def xml_header(xml)
|
109
|
+
xml.env(:Header) do
|
110
|
+
xml << (header.to_soap_xml rescue header.to_s) + wsse_header
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Adds a SOAP XML body to a given +xml+ Object.
|
115
|
+
def xml_body(xml)
|
116
|
+
xml.env(:Body) do
|
117
|
+
xml.tag!(:wsdl, *input_array) do
|
118
|
+
xml << (@body.to_soap_xml rescue @body.to_s)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns an Array of SOAP input names to append to the :wsdl namespace.
|
124
|
+
# Defaults to use the name of the SOAP action and may be an empty Array
|
125
|
+
# in case the specified SOAP input seems invalid.
|
126
|
+
def input_array
|
127
|
+
return [input.to_sym] unless input.blank?
|
128
|
+
return [action.to_sym] unless action.blank?
|
129
|
+
[]
|
130
|
+
end
|
131
|
+
|
132
|
+
# Returns the WSSE header or an empty String in case WSSE was not set.
|
133
|
+
def wsse_header
|
134
|
+
@wsse.respond_to?(:header) ? @wsse.header : ""
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
data/lib/savon/wsdl.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
module Savon
|
2
|
+
|
3
|
+
# Savon::WSDL
|
4
|
+
#
|
5
|
+
# Represents the WSDL document.
|
6
|
+
class WSDL
|
7
|
+
|
8
|
+
# Initializer, expects a Savon::Request.
|
9
|
+
def initialize(request)
|
10
|
+
@request = request
|
11
|
+
end
|
12
|
+
|
13
|
+
# Sets whether to use the WSDL.
|
14
|
+
attr_writer :enabled
|
15
|
+
|
16
|
+
# Returns whether to use the WSDL. Defaults to +true+.
|
17
|
+
def enabled?
|
18
|
+
@enabled.nil? ? true : @enabled
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the namespace URI of the WSDL.
|
22
|
+
def namespace_uri
|
23
|
+
@namespace_uri ||= stream.namespace_uri
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns an Array of available SOAP actions.
|
27
|
+
def soap_actions
|
28
|
+
@soap_actions ||= stream.operations.keys
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns a Hash of SOAP operations including their corresponding
|
32
|
+
# SOAP actions and inputs.
|
33
|
+
def operations
|
34
|
+
@operations ||= stream.operations
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the SOAP endpoint.
|
38
|
+
def soap_endpoint
|
39
|
+
@soap_endpoint ||= stream.soap_endpoint
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns +true+ for available methods and SOAP actions.
|
43
|
+
def respond_to?(method)
|
44
|
+
return true if soap_actions.include? method
|
45
|
+
super
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the raw WSDL document.
|
49
|
+
def to_s
|
50
|
+
@document ||= @request.wsdl.body
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# Returns the Savon::WSDLStream.
|
56
|
+
def stream
|
57
|
+
unless @stream
|
58
|
+
@stream = WSDLStream.new
|
59
|
+
REXML::Document.parse_stream to_s, @stream
|
60
|
+
end
|
61
|
+
@stream
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
# Savon::WSDLStream
|
67
|
+
#
|
68
|
+
# Stream listener for parsing the WSDL document.
|
69
|
+
class WSDLStream
|
70
|
+
|
71
|
+
# The main sections of a WSDL document.
|
72
|
+
Sections = %w(definitions types message portType binding service)
|
73
|
+
|
74
|
+
def initialize
|
75
|
+
@depth, @operations = 0, {}
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns the namespace URI.
|
79
|
+
attr_reader :namespace_uri
|
80
|
+
|
81
|
+
# Returns the SOAP operations.
|
82
|
+
attr_reader :operations
|
83
|
+
|
84
|
+
# Returns the SOAP endpoint.
|
85
|
+
attr_reader :soap_endpoint
|
86
|
+
|
87
|
+
# Hook method called when the stream parser encounters a starting tag.
|
88
|
+
def tag_start(tag, attrs)
|
89
|
+
@depth += 1
|
90
|
+
tag = tag.strip_namespace
|
91
|
+
|
92
|
+
@section = tag.to_sym if @depth <= 2 && Sections.include?(tag)
|
93
|
+
@namespace_uri ||= attrs["targetNamespace"] if @section == :definitions
|
94
|
+
@soap_endpoint ||= URI(attrs["location"]) if @section == :service && tag == "address"
|
95
|
+
|
96
|
+
operation_from tag, attrs if @section == :binding && tag == "operation"
|
97
|
+
end
|
98
|
+
|
99
|
+
# Hook method called when the stream parser encounters a closing tag.
|
100
|
+
def tag_end(tag)
|
101
|
+
@depth -= 1
|
102
|
+
end
|
103
|
+
|
104
|
+
# Stores available operations from a given tag +name+ and +attrs+.
|
105
|
+
def operation_from(tag, attrs)
|
106
|
+
@input = attrs["name"] if attrs["name"]
|
107
|
+
|
108
|
+
if attrs["soapAction"]
|
109
|
+
@action = !attrs["soapAction"].blank? ? attrs["soapAction"] : @input
|
110
|
+
@input = @action.split("/").last if !@input || @input.empty?
|
111
|
+
|
112
|
+
@operations[@input.snakecase.to_sym] = { :action => @action, :input => @input }
|
113
|
+
@input, @action = nil, nil
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Catches calls to unimplemented hook methods.
|
118
|
+
def method_missing(method, *args)
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|