regenersis-savon 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/.gitignore +10 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +12 -0
  4. data/CHANGELOG.md +639 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +20 -0
  7. data/README.md +42 -0
  8. data/Rakefile +7 -0
  9. data/lib/regenersis-savon.rb +1 -0
  10. data/lib/savon.rb +15 -0
  11. data/lib/savon/client.rb +168 -0
  12. data/lib/savon/core_ext/object.rb +14 -0
  13. data/lib/savon/core_ext/string.rb +23 -0
  14. data/lib/savon/error.rb +6 -0
  15. data/lib/savon/global.rb +115 -0
  16. data/lib/savon/hooks/group.rb +46 -0
  17. data/lib/savon/hooks/hook.rb +36 -0
  18. data/lib/savon/http/error.rb +42 -0
  19. data/lib/savon/model.rb +103 -0
  20. data/lib/savon/soap.rb +21 -0
  21. data/lib/savon/soap/fault.rb +59 -0
  22. data/lib/savon/soap/request.rb +71 -0
  23. data/lib/savon/soap/response.rb +109 -0
  24. data/lib/savon/soap/xml.rb +227 -0
  25. data/lib/savon/version.rb +5 -0
  26. data/lib/savon/wasabi/document.rb +41 -0
  27. data/regenersis-savon.gemspec +35 -0
  28. data/spec/fixtures/gzip/message.gz +0 -0
  29. data/spec/fixtures/response/another_soap_fault.xml +14 -0
  30. data/spec/fixtures/response/authentication.xml +14 -0
  31. data/spec/fixtures/response/header.xml +13 -0
  32. data/spec/fixtures/response/list.xml +18 -0
  33. data/spec/fixtures/response/multi_ref.xml +39 -0
  34. data/spec/fixtures/response/soap_fault.xml +8 -0
  35. data/spec/fixtures/response/soap_fault12.xml +18 -0
  36. data/spec/fixtures/response/taxcloud.xml +1 -0
  37. data/spec/fixtures/wsdl/authentication.xml +63 -0
  38. data/spec/fixtures/wsdl/lower_camel.xml +52 -0
  39. data/spec/fixtures/wsdl/multiple_namespaces.xml +61 -0
  40. data/spec/fixtures/wsdl/multiple_types.xml +60 -0
  41. data/spec/fixtures/wsdl/taxcloud.xml +934 -0
  42. data/spec/savon/client_spec.rb +461 -0
  43. data/spec/savon/core_ext/object_spec.rb +19 -0
  44. data/spec/savon/core_ext/string_spec.rb +37 -0
  45. data/spec/savon/http/error_spec.rb +52 -0
  46. data/spec/savon/model_spec.rb +194 -0
  47. data/spec/savon/savon_spec.rb +85 -0
  48. data/spec/savon/soap/fault_spec.rb +89 -0
  49. data/spec/savon/soap/request_spec.rb +57 -0
  50. data/spec/savon/soap/response_spec.rb +224 -0
  51. data/spec/savon/soap/xml_spec.rb +309 -0
  52. data/spec/savon/soap_spec.rb +16 -0
  53. data/spec/savon/wasabi/document_spec.rb +45 -0
  54. data/spec/spec_helper.rb +15 -0
  55. data/spec/support/endpoint.rb +25 -0
  56. data/spec/support/fixture.rb +35 -0
  57. metadata +323 -0
@@ -0,0 +1,227 @@
1
+ require "builder"
2
+ require "gyoku"
3
+ require "nori"
4
+
5
+ require "savon/soap"
6
+
7
+ Nori.configure do |config|
8
+ config.strip_namespaces = true
9
+ config.convert_tags_to { |tag| tag.snakecase.to_sym }
10
+ end
11
+
12
+ module Savon
13
+ module SOAP
14
+
15
+ # = Savon::SOAP::XML
16
+ #
17
+ # Represents the SOAP request XML. Contains various global and per request/instance settings
18
+ # like the SOAP version, header, body and namespaces.
19
+ class XML
20
+
21
+ # XML Schema Type namespaces.
22
+ SchemaTypes = {
23
+ "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
24
+ "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance"
25
+ }
26
+
27
+ # Accepts an +endpoint+, an +input+ tag and a SOAP +body+.
28
+ def initialize(endpoint = nil, input = nil, body = nil)
29
+ self.endpoint = endpoint if endpoint
30
+ self.input = input if input
31
+ self.body = body if body
32
+ end
33
+
34
+ # Accessor for the SOAP +input+ tag.
35
+ attr_accessor :input
36
+
37
+ # Accessor for the SOAP +endpoint+.
38
+ attr_accessor :endpoint
39
+
40
+ # Sets the SOAP +version+.
41
+ def version=(version)
42
+ raise ArgumentError, "Invalid SOAP version: #{version}" unless SOAP::Versions.include? version
43
+ @version = version
44
+ end
45
+
46
+ # Returns the SOAP +version+. Defaults to <tt>Savon.soap_version</tt>.
47
+ def version
48
+ @version ||= Savon.soap_version
49
+ end
50
+
51
+ # Sets the SOAP +header+ Hash.
52
+ attr_writer :header
53
+
54
+ # Returns the SOAP +header+. Defaults to an empty Hash.
55
+ def header
56
+ @header ||= Savon.soap_header.nil? ? {} : Savon.soap_header
57
+ end
58
+
59
+ # Sets the SOAP envelope namespace.
60
+ attr_writer :env_namespace
61
+
62
+ # Returns the SOAP envelope namespace. Uses the global namespace if set Defaults to :env.
63
+ def env_namespace
64
+ @env_namespace ||= Savon.env_namespace.nil? ? :env : Savon.env_namespace
65
+ end
66
+
67
+ # Sets the +namespaces+ Hash.
68
+ attr_writer :namespaces
69
+
70
+ # Returns the +namespaces+. Defaults to a Hash containing the SOAP envelope namespace.
71
+ def namespaces
72
+ @namespaces ||= begin
73
+ key = env_namespace.blank? ? "xmlns" : "xmlns:#{env_namespace}"
74
+ { key => SOAP::Namespace[version] }
75
+ end
76
+ end
77
+
78
+ def namespace_by_uri(uri)
79
+ namespaces.each do |candidate_identifier, candidate_uri|
80
+ return candidate_identifier.gsub(/^xmlns:/, '') if candidate_uri == uri
81
+ end
82
+ nil
83
+ end
84
+
85
+ def used_namespaces
86
+ @used_namespaces ||= {}
87
+ end
88
+
89
+ def use_namespace(path, uri)
90
+ @internal_namespace_count ||= 0
91
+
92
+ unless identifier = namespace_by_uri(uri)
93
+ identifier = "ins#{@internal_namespace_count}"
94
+ namespaces["xmlns:#{identifier}"] = uri
95
+ @internal_namespace_count += 1
96
+ end
97
+
98
+ used_namespaces[path] = identifier
99
+ end
100
+
101
+ def types
102
+ @types ||= {}
103
+ end
104
+
105
+ # Sets the default namespace identifier.
106
+ attr_writer :namespace_identifier
107
+
108
+ # Returns the default namespace identifier.
109
+ def namespace_identifier
110
+ @namespace_identifier ||= :wsdl
111
+ end
112
+
113
+ # Returns whether all local elements should be namespaced. Might be set to :qualified,
114
+ # but defaults to :unqualified.
115
+ def element_form_default
116
+ @element_form_default ||= :unqualified
117
+ end
118
+
119
+ # Sets whether all local elements should be namespaced.
120
+ attr_writer :element_form_default
121
+
122
+ # Accessor for the default namespace URI.
123
+ attr_accessor :namespace
124
+
125
+ # Accessor for the <tt>Savon::WSSE</tt> object.
126
+ attr_accessor :wsse
127
+
128
+ # Accepts a +block+ and yields a <tt>Builder::XmlMarkup</tt> object to let you create
129
+ # custom body XML.
130
+ def body
131
+ @body = yield builder(nil) if block_given?
132
+ @body
133
+ end
134
+
135
+ # Sets the SOAP +body+. Expected to be a Hash that can be translated to XML via `Gyoku.xml`
136
+ # or any other Object responding to to_s.
137
+ attr_writer :body
138
+
139
+ # Accepts a +block+ and yields a <tt>Builder::XmlMarkup</tt> object to let you create
140
+ # a completely custom XML.
141
+ def xml(directive_tag = :xml, attrs = {})
142
+ @xml = yield builder(directive_tag, attrs) if block_given?
143
+ end
144
+
145
+ # Accepts an XML String and lets you specify a completely custom request body.
146
+ attr_writer :xml
147
+
148
+ # Returns the XML for a SOAP request.
149
+ def to_xml
150
+ @xml ||= tag(builder, :Envelope, complete_namespaces) do |xml|
151
+ tag(xml, :Header) { xml << header_for_xml } unless header_for_xml.empty?
152
+
153
+ if input.nil?
154
+ tag(xml, :Body)
155
+ else
156
+ tag(xml, :Body) { xml.tag!(*add_namespace_to_input) { xml << body_to_xml } }
157
+ end
158
+ end
159
+ end
160
+
161
+ private
162
+
163
+ # Returns a new <tt>Builder::XmlMarkup</tt> object.
164
+ def builder(directive_tag = :xml, attrs = {})
165
+ builder = Builder::XmlMarkup.new
166
+ builder.instruct!(directive_tag, attrs) if directive_tag
167
+ builder
168
+ end
169
+
170
+ # Expects a builder +xml+ instance, a tag +name+ and accepts optional +namespaces+
171
+ # and a block to create an XML tag.
172
+ def tag(xml, name, namespaces = {}, &block)
173
+ return xml.tag! name, namespaces, &block if env_namespace.blank?
174
+ xml.tag! env_namespace, name, namespaces, &block
175
+ end
176
+
177
+ # Returns the complete Hash of namespaces.
178
+ def complete_namespaces
179
+ defaults = SchemaTypes.dup
180
+ defaults["xmlns:#{namespace_identifier}"] = namespace if namespace
181
+ defaults.merge namespaces
182
+ end
183
+
184
+ # Returns the SOAP header as an XML String.
185
+ def header_for_xml
186
+ @header_for_xml ||= Gyoku.xml(header) + wsse_header
187
+ end
188
+
189
+ # Returns the WSSE header or an empty String in case WSSE was not set.
190
+ def wsse_header
191
+ wsse.respond_to?(:to_xml) ? wsse.to_xml : ""
192
+ end
193
+
194
+ # Returns the SOAP body as an XML String.
195
+ def body_to_xml
196
+ return body.to_s unless body.kind_of? Hash
197
+ Gyoku.xml add_namespaces_to_body(body), :element_form_default => element_form_default, :namespace => namespace_identifier
198
+ end
199
+
200
+ def add_namespaces_to_body(hash, path = [input[1].to_s])
201
+ return unless hash
202
+ return hash if hash.kind_of?(Array)
203
+ return hash.to_s unless hash.kind_of? Hash
204
+
205
+ hash.inject({}) do |newhash, (key, value)|
206
+ camelcased_key = Gyoku::XMLKey.create(key)
207
+ newpath = path + [camelcased_key]
208
+
209
+ if used_namespaces[newpath]
210
+ newhash.merge(
211
+ "#{used_namespaces[newpath]}:#{camelcased_key}" =>
212
+ add_namespaces_to_body(value, types[newpath] ? [types[newpath]] : newpath)
213
+ )
214
+ else
215
+ newhash.merge(key => value)
216
+ end
217
+ end
218
+ end
219
+
220
+ def add_namespace_to_input
221
+ return input.compact unless used_namespaces[[input[1].to_s]]
222
+ [used_namespaces[[input[1].to_s]], input[1], input[2]]
223
+ end
224
+
225
+ end
226
+ end
227
+ end
@@ -0,0 +1,5 @@
1
+ module Savon
2
+
3
+ Version = "1.0.0"
4
+
5
+ end
@@ -0,0 +1,41 @@
1
+ require "wasabi"
2
+ require "httpi/request"
3
+
4
+ module Savon
5
+ module Wasabi
6
+
7
+ # = Savon::Wasabi::Document
8
+ #
9
+ # Extends the document handling of the <tt>Wasabi::Document</tt> by
10
+ # adding support for remote and local WSDL documents.
11
+ class Document < ::Wasabi::Document
12
+
13
+ # Hooks into Wasabi and extends its document handling.
14
+ def xml
15
+ @xml ||= document.kind_of?(String) ? resolve_document : document
16
+ end
17
+
18
+ # Sets the <tt>HTTPI::Request</tt> for remote WSDL documents.
19
+ attr_writer :request
20
+
21
+ private
22
+
23
+ # Sets up and returns the <tt>HTTPI::Request</tt>.
24
+ def request
25
+ @request ||= HTTPI::Request.new
26
+ @request.url = document
27
+ @request
28
+ end
29
+
30
+ # Resolves and returns the raw WSDL document.
31
+ def resolve_document
32
+ case document
33
+ when /^http[s]?:/ then HTTPI.get(request).body
34
+ when /^</ then document
35
+ else File.read(document)
36
+ end
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,35 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $:.unshift lib unless $:.include? lib
3
+
4
+ require "savon/version"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "regenersis-savon"
8
+ s.version = Savon::Version
9
+ s.authors = "Daniel Harrington"
10
+ s.email = "me@rubiii.com"
11
+ s.homepage = "http://savonrb.com"
12
+ s.summary = "Heavy metal Ruby SOAP client"
13
+ s.description = "Ruby's heavy metal SOAP client"
14
+
15
+ s.rubyforge_project = s.name
16
+
17
+ s.add_dependency "builder", ">= 2.1.2"
18
+ s.add_dependency "nori", "~> 1.0"
19
+ s.add_dependency "regenersis-httpi", "~> 0.9"
20
+ s.add_dependency "wasabi", "~> 2.0"
21
+ s.add_dependency "akami", "~> 1.0"
22
+ s.add_dependency "gyoku", ">= 0.4.0"
23
+ s.add_dependency "nokogiri", ">= 1.4.0"
24
+
25
+ s.add_development_dependency "rake", "~> 0.8.7"
26
+ s.add_development_dependency "rspec", "~> 2.5.0"
27
+ s.add_development_dependency "mocha", "~> 0.9.8"
28
+ s.add_development_dependency "timecop", "~> 0.3.5"
29
+
30
+ s.add_development_dependency "autotest"
31
+ s.add_development_dependency "ZenTest", "4.5.0"
32
+
33
+ s.files = `git ls-files`.split("\n")
34
+ s.require_path = "lib"
35
+ end
@@ -0,0 +1,14 @@
1
+ <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
2
+ xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
3
+ xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
4
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema">
6
+ <SOAP-ENV:Body>
7
+ <SOAP-ENV:Fault>
8
+ <faultcode>ERR_NO_SESSION</faultcode>
9
+ <faultfactor>doGetItemsInfo - Wrong session</faultfactor>
10
+ <faultstring>Wrong session message</faultstring>
11
+ <detail><soapVal><ERRNO xsi:type="xsd:string">80:1289245853:55</ERRNO></soapVal></detail>
12
+ </SOAP-ENV:Fault>
13
+ </SOAP-ENV:Body>
14
+ </SOAP-ENV:Envelope>
@@ -0,0 +1,14 @@
1
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
2
+ <soap:Body>
3
+ <ns2:authenticateResponse xmlns:ns2="http://v1_0.ws.user.example.com">
4
+ <return>
5
+ <authenticationValue>
6
+ <token>a68d1d6379b62ff339a0e0c69ed4d9cf</token>
7
+ <tokenHash>AAAJxA;cIedoT;mY10ExZwG6JuKgp2OYKxow==</tokenHash>
8
+ <client>radclient</client>
9
+ </authenticationValue>
10
+ <success>true</success>
11
+ </return>
12
+ </ns2:authenticateResponse>
13
+ </soap:Body>
14
+ </soap:Envelope>
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
3
+ <soap:Header xmlns="http://webservices.somewhere.com/definitions">
4
+ <SessionNumber>ABCD1234</SessionNumber>
5
+ </soap:Header>
6
+ <soap:Body>
7
+ <AuthenticateReply xmlns="http://xml.somewhere.com/ABCD">
8
+ <processStatus>
9
+ <statusCode>P</statusCode>
10
+ </processStatus>
11
+ </AuthenticateReply>
12
+ </soap:Body>
13
+ </soap:Envelope>
@@ -0,0 +1,18 @@
1
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
2
+ <soapenv:Body>
3
+ <MultiNamespacedEntryResponse xmlns="http://www.example.com/BusinessRulesEngine/xsd">
4
+ <history>
5
+ <ns10:case xmlns:ns10="http://www.example.com/Common/xsd">
6
+ <ns10:logTime>2010-09-21T18:22:01.558+10:00</ns10:logTime>
7
+ <ns10:logType>Notes Log</ns10:logType>
8
+ <ns10:logText>test</ns10:logText>
9
+ </ns10:case>
10
+ <ns11:case xmlns:ns11="http://www.example.com/Common/xsd">
11
+ <ns11:logTime>2010-09-21T18:22:07.038+10:00</ns11:logTime>
12
+ <ns11:logType>Notes Log</ns11:logType>
13
+ <ns11:logText>another test</ns11:logText>
14
+ </ns11:case>
15
+ </history>
16
+ </MultiNamespacedEntryResponse>
17
+ </soapenv:Body>
18
+ </soapenv:Envelope>
@@ -0,0 +1,39 @@
1
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
2
+ <soapenv:Body>
3
+ <ns1:listResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://ws.example.com">
4
+ <listReturn soapenc:arrayType="ns2:HistoryEntry[3]" xsi:type="soapenc:Array" xmlns:ns2="http://ws.example.com/ws/history" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
5
+ <listReturn href="#id0"/>
6
+ <listReturn href="#id1"/>
7
+ <listReturn href="#id2"/>
8
+ </listReturn>
9
+ </ns1:listResponse>
10
+ <multiRef id="id1" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns5:HistoryEntry" xmlns:ns5="http://ws.example.com/ws/history" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
11
+ <date xsi:type="xsd:dateTime">2009-09-22T13:47:23.000Z</date>
12
+ <location xsi:type="soapenc:string">Archive</location>
13
+ <mailId href="#id9"/>
14
+ <referenceId href="#id8"/>
15
+ <state xsi:type="soapenc:string">Original</state>
16
+ <subject xsi:type="soapenc:string">Mail from 09-22-2009: Misc</subject>
17
+ </multiRef>
18
+ <multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns6:HistoryEntry" xmlns:ns6="http://ws.example.com/ws/history" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
19
+ <date xsi:type="xsd:dateTime">2009-04-30T06:38:34.000Z</date>
20
+ <location xsi:type="soapenc:string">Archive</location>
21
+ <mailId href="#id10"/>
22
+ <referenceId href="#id8"/>
23
+ <state xsi:type="soapenc:string">Original</state>
24
+ <subject xsi:type="soapenc:string">Mail from 04-29-2009: Technical support</subject>
25
+ </multiRef>
26
+ <multiRef id="id2" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns7:HistoryEntry" xmlns:ns7="http://ws.example.com/ws/history" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
27
+ <date xsi:type="xsd:dateTime">2009-12-18T15:43:21.000Z</date>
28
+ <location xsi:type="soapenc:string">Archive</location>
29
+ <mailId href="#id11"/>
30
+ <referenceId href="#id8"/>
31
+ <state xsi:type="soapenc:string">Original</state>
32
+ <subject xsi:type="soapenc:string">Mail from 12-17-2009: Misc</subject>
33
+ </multiRef>
34
+ <multiRef id="id11" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:int" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">972219</multiRef>
35
+ <multiRef id="id10" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:int" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">708021</multiRef>
36
+ <multiRef id="id8" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:int" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">0</multiRef>
37
+ <multiRef id="id9" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:int" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">855763</multiRef>
38
+ </soapenv:Body>
39
+ </soapenv:Envelope>
@@ -0,0 +1,8 @@
1
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
2
+ <soap:Body>
3
+ <soap:Fault>
4
+ <faultcode>soap:Server</faultcode>
5
+ <faultstring>Fault occurred while processing.</faultstring>
6
+ </soap:Fault>
7
+ </soap:Body>
8
+ </soap:Envelope>
@@ -0,0 +1,18 @@
1
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:m="http://www.example.org/timeouts">
2
+ <soap:Body>
3
+ <soap:Fault>
4
+ <Code>
5
+ <Value>soap:Sender</Value>
6
+ <Subcode>
7
+ <Value>m:MessageTimeout</Value>
8
+ </Subcode>
9
+ </Code>
10
+ <Reason>
11
+ <Text xml:lang="en">Sender Timeout</Text>
12
+ </Reason>
13
+ <Detail>
14
+ <m:MaxTime>P5M</m:MaxTime>
15
+ </Detail>
16
+ </soap:Fault>
17
+ </soap:Body>
18
+ </soap:Envelope>