savon-SU 2.11.1b

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.travis.yml +15 -0
  4. data/.yardopts +6 -0
  5. data/CHANGELOG.md +1098 -0
  6. data/CONTRIBUTING.md +46 -0
  7. data/Gemfile +18 -0
  8. data/LICENSE +20 -0
  9. data/README.md +69 -0
  10. data/Rakefile +14 -0
  11. data/donate.png +0 -0
  12. data/lib/savon.rb +27 -0
  13. data/lib/savon/block_interface.rb +26 -0
  14. data/lib/savon/builder.rb +205 -0
  15. data/lib/savon/client.rb +102 -0
  16. data/lib/savon/core_ext/string.rb +29 -0
  17. data/lib/savon/header.rb +93 -0
  18. data/lib/savon/http_error.rb +27 -0
  19. data/lib/savon/log_message.rb +52 -0
  20. data/lib/savon/message.rb +37 -0
  21. data/lib/savon/mock.rb +5 -0
  22. data/lib/savon/mock/expectation.rb +80 -0
  23. data/lib/savon/mock/spec_helper.rb +62 -0
  24. data/lib/savon/model.rb +84 -0
  25. data/lib/savon/operation.rb +144 -0
  26. data/lib/savon/options.rb +410 -0
  27. data/lib/savon/qualified_message.rb +50 -0
  28. data/lib/savon/request.rb +97 -0
  29. data/lib/savon/request_logger.rb +48 -0
  30. data/lib/savon/response.rb +113 -0
  31. data/lib/savon/soap_fault.rb +50 -0
  32. data/lib/savon/version.rb +3 -0
  33. data/savon-SU.gemspec +46 -0
  34. data/spec/fixtures/gzip/message.gz +0 -0
  35. data/spec/fixtures/response/another_soap_fault.xml +14 -0
  36. data/spec/fixtures/response/authentication.xml +14 -0
  37. data/spec/fixtures/response/f5.xml +39 -0
  38. data/spec/fixtures/response/header.xml +13 -0
  39. data/spec/fixtures/response/list.xml +18 -0
  40. data/spec/fixtures/response/multi_ref.xml +39 -0
  41. data/spec/fixtures/response/soap_fault.xml +8 -0
  42. data/spec/fixtures/response/soap_fault12.xml +18 -0
  43. data/spec/fixtures/response/soap_fault_funky.xml +8 -0
  44. data/spec/fixtures/response/taxcloud.xml +1 -0
  45. data/spec/fixtures/ssl/client_cert.pem +16 -0
  46. data/spec/fixtures/ssl/client_encrypted_key.pem +30 -0
  47. data/spec/fixtures/ssl/client_encrypted_key_cert.pem +24 -0
  48. data/spec/fixtures/ssl/client_key.pem +15 -0
  49. data/spec/fixtures/wsdl/authentication.xml +63 -0
  50. data/spec/fixtures/wsdl/betfair.xml +2981 -0
  51. data/spec/fixtures/wsdl/edialog.xml +15416 -0
  52. data/spec/fixtures/wsdl/interhome.xml +2137 -0
  53. data/spec/fixtures/wsdl/lower_camel.xml +52 -0
  54. data/spec/fixtures/wsdl/multiple_namespaces.xml +92 -0
  55. data/spec/fixtures/wsdl/multiple_types.xml +60 -0
  56. data/spec/fixtures/wsdl/no_message_tag.xml +1267 -0
  57. data/spec/fixtures/wsdl/taxcloud.xml +934 -0
  58. data/spec/fixtures/wsdl/team_software.xml +1 -0
  59. data/spec/fixtures/wsdl/vies.xml +176 -0
  60. data/spec/fixtures/wsdl/wasmuth.xml +153 -0
  61. data/spec/integration/centra_spec.rb +66 -0
  62. data/spec/integration/email_example_spec.rb +32 -0
  63. data/spec/integration/random_quote_spec.rb +23 -0
  64. data/spec/integration/ratp_example_spec.rb +28 -0
  65. data/spec/integration/stockquote_example_spec.rb +28 -0
  66. data/spec/integration/support/application.rb +82 -0
  67. data/spec/integration/support/server.rb +84 -0
  68. data/spec/integration/temperature_example_spec.rb +46 -0
  69. data/spec/integration/zipcode_example_spec.rb +42 -0
  70. data/spec/savon/builder_spec.rb +137 -0
  71. data/spec/savon/client_spec.rb +271 -0
  72. data/spec/savon/core_ext/string_spec.rb +37 -0
  73. data/spec/savon/features/message_tag_spec.rb +61 -0
  74. data/spec/savon/http_error_spec.rb +49 -0
  75. data/spec/savon/log_message_spec.rb +44 -0
  76. data/spec/savon/message_spec.rb +70 -0
  77. data/spec/savon/mock_spec.rb +174 -0
  78. data/spec/savon/model_spec.rb +182 -0
  79. data/spec/savon/observers_spec.rb +92 -0
  80. data/spec/savon/operation_spec.rb +230 -0
  81. data/spec/savon/options_spec.rb +1064 -0
  82. data/spec/savon/qualified_message_spec.rb +20 -0
  83. data/spec/savon/request_logger_spec.rb +37 -0
  84. data/spec/savon/request_spec.rb +496 -0
  85. data/spec/savon/response_spec.rb +270 -0
  86. data/spec/savon/soap_fault_spec.rb +131 -0
  87. data/spec/spec_helper.rb +30 -0
  88. data/spec/support/adapters.rb +48 -0
  89. data/spec/support/endpoint.rb +25 -0
  90. data/spec/support/fixture.rb +39 -0
  91. data/spec/support/integration.rb +9 -0
  92. data/spec/support/stdout.rb +25 -0
  93. metadata +317 -0
@@ -0,0 +1,50 @@
1
+ require "gyoku"
2
+
3
+ module Savon
4
+ class QualifiedMessage
5
+
6
+ def initialize(types, used_namespaces, key_converter)
7
+ @types = types
8
+ @used_namespaces = used_namespaces
9
+ @key_converter = key_converter
10
+ end
11
+
12
+ def to_hash(hash, path)
13
+ return hash unless hash
14
+ return hash.map { |value| to_hash(value, path) } if hash.kind_of?(Array)
15
+ return hash.to_s unless hash.kind_of? Hash
16
+
17
+ hash.inject({}) do |newhash, (key, value)|
18
+ if key == :order!
19
+ add_namespaces_to_values(value, path)
20
+ newhash.merge(key => value)
21
+ else
22
+ translated_key = Gyoku.xml_tag(key, :key_converter => @key_converter).to_s
23
+ translated_key << "!" if key[-1] == "!"
24
+ newpath = path + [translated_key]
25
+
26
+ if @used_namespaces[newpath]
27
+ newhash.merge(
28
+ "#{@used_namespaces[newpath]}:#{translated_key}" =>
29
+ to_hash(value, @types[newpath] ? [@types[newpath]] : newpath)
30
+ )
31
+ else
32
+ newhash.merge(translated_key => value)
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def add_namespaces_to_values(values, path)
41
+ values.collect! { |value|
42
+ camelcased_value = Gyoku.xml_tag(value, :key_converter => @key_converter)
43
+ namespace_path = path + [camelcased_value.to_s]
44
+ namespace = @used_namespaces[namespace_path]
45
+ "#{namespace.blank? ? '' : namespace + ":"}#{camelcased_value}"
46
+ }
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,97 @@
1
+ require "httpi"
2
+
3
+ module Savon
4
+ class HTTPRequest
5
+
6
+ def initialize(globals, http_request = nil)
7
+ @globals = globals
8
+ @http_request = http_request || HTTPI::Request.new
9
+ end
10
+
11
+ def build
12
+ @http_request
13
+ end
14
+
15
+ private
16
+
17
+ def configure_proxy
18
+ @http_request.proxy = @globals[:proxy] if @globals.include? :proxy
19
+ end
20
+
21
+ def configure_timeouts
22
+ @http_request.open_timeout = @globals[:open_timeout] if @globals.include? :open_timeout
23
+ @http_request.read_timeout = @globals[:read_timeout] if @globals.include? :read_timeout
24
+ end
25
+
26
+ def configure_ssl
27
+ @http_request.auth.ssl.ssl_version = @globals[:ssl_version] if @globals.include? :ssl_version
28
+ @http_request.auth.ssl.verify_mode = @globals[:ssl_verify_mode] if @globals.include? :ssl_verify_mode
29
+
30
+ @http_request.auth.ssl.cert_key_file = @globals[:ssl_cert_key_file] if @globals.include? :ssl_cert_key_file
31
+ @http_request.auth.ssl.cert_key = @globals[:ssl_cert_key] if @globals.include? :ssl_cert_key
32
+ @http_request.auth.ssl.cert_file = @globals[:ssl_cert_file] if @globals.include? :ssl_cert_file
33
+ @http_request.auth.ssl.cert = @globals[:ssl_cert] if @globals.include? :ssl_cert
34
+ @http_request.auth.ssl.ca_cert_file = @globals[:ssl_ca_cert_file] if @globals.include? :ssl_ca_cert_file
35
+ @http_request.auth.ssl.ca_cert = @globals[:ssl_ca_cert] if @globals.include? :ssl_ca_cert
36
+
37
+ @http_request.auth.ssl.cert_key_password = @globals[:ssl_cert_key_password] if @globals.include? :ssl_cert_key_password
38
+ end
39
+
40
+ def configure_auth
41
+ @http_request.auth.basic(*@globals[:basic_auth]) if @globals.include? :basic_auth
42
+ @http_request.auth.digest(*@globals[:digest_auth]) if @globals.include? :digest_auth
43
+ @http_request.auth.ntlm(*@globals[:ntlm]) if @globals.include? :ntlm
44
+ end
45
+
46
+ def configure_redirect_handling
47
+ if @globals.include? :follow_redirects
48
+ @http_request.follow_redirect = @globals[:follow_redirects]
49
+ end
50
+ end
51
+ end
52
+
53
+ class WSDLRequest < HTTPRequest
54
+
55
+ def build
56
+ configure_proxy
57
+ configure_timeouts
58
+ configure_ssl
59
+ configure_auth
60
+ configure_redirect_handling
61
+
62
+ @http_request
63
+ end
64
+ end
65
+
66
+ class SOAPRequest < HTTPRequest
67
+
68
+ CONTENT_TYPE = {
69
+ 1 => "text/xml;charset=%s",
70
+ 2 => "application/soap+xml;charset=%s"
71
+ }
72
+
73
+ def build(options = {})
74
+ configure_proxy
75
+ configure_cookies options[:cookies]
76
+ configure_timeouts
77
+ configure_headers options[:soap_action]
78
+ configure_ssl
79
+ configure_auth
80
+ configure_redirect_handling
81
+
82
+ @http_request
83
+ end
84
+
85
+ private
86
+
87
+ def configure_cookies(cookies)
88
+ @http_request.set_cookies(cookies) if cookies
89
+ end
90
+
91
+ def configure_headers(soap_action)
92
+ @http_request.headers = @globals[:headers] if @globals.include? :headers
93
+ @http_request.headers["SOAPAction"] ||= %{"#{soap_action}"} if soap_action
94
+ @http_request.headers["Content-Type"] ||= CONTENT_TYPE[@globals[:soap_version]] % @globals[:encoding]
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,48 @@
1
+ require "savon/log_message"
2
+
3
+ module Savon
4
+ class RequestLogger
5
+
6
+ def initialize(globals)
7
+ @globals = globals
8
+ end
9
+
10
+ def log(request, &http_request)
11
+ log_request(request) if log?
12
+ response = http_request.call
13
+ log_response(response) if log?
14
+
15
+ response
16
+ end
17
+
18
+ def logger
19
+ @globals[:logger]
20
+ end
21
+
22
+ def log?
23
+ @globals[:log]
24
+ end
25
+
26
+ private
27
+
28
+ def log_request(request)
29
+ logger.info { "SOAP request: #{request.url}" }
30
+ logger.info { headers_to_log(request.headers) }
31
+ logger.debug { body_to_log(request.body) }
32
+ end
33
+
34
+ def log_response(response)
35
+ logger.info { "SOAP response (status #{response.code})" }
36
+ logger.debug { body_to_log(response.body) }
37
+ end
38
+
39
+ def headers_to_log(headers)
40
+ headers.map { |key, value| "#{key}: #{value}" }.join(", ")
41
+ end
42
+
43
+ def body_to_log(body)
44
+ LogMessage.new(body, @globals[:filters], @globals[:pretty_print_xml]).to_s
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,113 @@
1
+ require "nori"
2
+ require "savon/soap_fault"
3
+ require "savon/http_error"
4
+
5
+ module Savon
6
+ class Response
7
+
8
+ def initialize(http, globals, locals)
9
+ @http = http
10
+ @globals = globals
11
+ @locals = locals
12
+
13
+ build_soap_and_http_errors!
14
+ raise_soap_and_http_errors! if @globals[:raise_errors]
15
+ end
16
+
17
+ attr_reader :http, :globals, :locals, :soap_fault, :http_error
18
+
19
+ def success?
20
+ !soap_fault? && !http_error?
21
+ end
22
+ alias_method :successful?, :success?
23
+
24
+ def soap_fault?
25
+ SOAPFault.present?(@http, xml)
26
+ end
27
+
28
+ def http_error?
29
+ HTTPError.present? @http
30
+ end
31
+
32
+ def header
33
+ find('Header')
34
+ end
35
+
36
+ def body
37
+ find('Body')
38
+ end
39
+
40
+ alias_method :to_hash, :body
41
+
42
+ def to_array(*path)
43
+ result = path.inject body do |memo, key|
44
+ return [] if memo[key].nil?
45
+ memo[key]
46
+ end
47
+
48
+ result.kind_of?(Array) ? result.compact : [result].compact
49
+ end
50
+
51
+ def hash
52
+ @hash ||= nori.parse(xml)
53
+ end
54
+
55
+ def xml
56
+ @http.body
57
+ end
58
+
59
+ alias_method :to_xml, :xml
60
+ alias_method :to_s, :xml
61
+
62
+ def doc
63
+ @doc ||= Nokogiri.XML(xml)
64
+ end
65
+
66
+ def xpath(path, namespaces = nil)
67
+ doc.xpath(path, namespaces || xml_namespaces)
68
+ end
69
+
70
+ def find(*path)
71
+ envelope = nori.find(hash, 'Envelope')
72
+ raise_invalid_response_error! unless envelope
73
+
74
+ nori.find(envelope, *path)
75
+ end
76
+
77
+ private
78
+
79
+ def build_soap_and_http_errors!
80
+ @soap_fault = SOAPFault.new(@http, nori, xml) if soap_fault?
81
+ @http_error = HTTPError.new(@http) if http_error?
82
+ end
83
+
84
+ def raise_soap_and_http_errors!
85
+ raise soap_fault if soap_fault?
86
+ raise http_error if http_error?
87
+ end
88
+
89
+ def raise_invalid_response_error!
90
+ raise InvalidResponseError, "Unable to parse response body:\n" + xml.inspect
91
+ end
92
+
93
+ def xml_namespaces
94
+ @xml_namespaces ||= doc.collect_namespaces
95
+ end
96
+
97
+ def nori
98
+ return @nori if @nori
99
+
100
+ nori_options = {
101
+ :strip_namespaces => @globals[:strip_namespaces],
102
+ :convert_tags_to => @globals[:convert_response_tags_to],
103
+ :convert_attributes_to => @globals[:convert_attributes_to],
104
+ :advanced_typecasting => @locals[:advanced_typecasting],
105
+ :parser => @locals[:response_parser]
106
+ }
107
+
108
+ non_nil_nori_options = nori_options.reject { |_, value| value.nil? }
109
+ @nori = Nori.new(non_nil_nori_options)
110
+ end
111
+
112
+ end
113
+ end
@@ -0,0 +1,50 @@
1
+ require "savon"
2
+
3
+ module Savon
4
+ class SOAPFault < Error
5
+
6
+ def self.present?(http, xml = nil)
7
+ xml ||= http.body
8
+ fault_node = xml.include?("Fault>")
9
+ soap1_fault = xml.include?("faultcode>") && xml.include?("faultstring>")
10
+ soap2_fault = xml.include?("Code>") && xml.include?("Reason>")
11
+
12
+ fault_node && (soap1_fault || soap2_fault)
13
+ end
14
+
15
+ def initialize(http, nori, xml = nil)
16
+ @xml = xml
17
+ @http = http
18
+ @nori = nori
19
+ end
20
+
21
+ attr_reader :http, :nori, :xml
22
+
23
+ def to_s
24
+ fault = nori.find(to_hash, 'Fault') || nori.find(to_hash, 'ServiceFault')
25
+ message_by_version(fault)
26
+ end
27
+
28
+ def to_hash
29
+ parsed = nori.parse(xml || http.body)
30
+ nori.find(parsed, 'Envelope', 'Body')
31
+ end
32
+
33
+ private
34
+
35
+ def message_by_version(fault)
36
+ if nori.find(fault, 'faultcode')
37
+ code = nori.find(fault, 'faultcode')
38
+ text = nori.find(fault, 'faultstring')
39
+
40
+ "(#{code}) #{text}"
41
+ elsif nori.find(fault, 'Code')
42
+ code = nori.find(fault, 'Code', 'Value')
43
+ text = nori.find(fault, 'Reason', 'Text')
44
+
45
+ "(#{code}) #{text}"
46
+ end
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,3 @@
1
+ module Savon
2
+ VERSION = '2.11.1b'
3
+ end
@@ -0,0 +1,46 @@
1
+ # -*- encoding : utf-8 -*-
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $:.unshift lib unless $:.include? lib
4
+
5
+ require "savon/version"
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "savon-SU"
9
+ s.version = Savon::VERSION
10
+ s.authors = "Daniel Harrington (Modified by Dimitris Mitsopoulos)"
11
+ s.email = "me@rubiii.com (sepultribe666@gmail.com)"
12
+ s.homepage = "http://savonrb.com"
13
+ s.summary = "Heavy metal SOAP client"
14
+ s.description = "Modified options.rb for error-free use in Sketchup and client.rb to add `List Parameters` method"
15
+ s.required_ruby_version = '>= 1.9.2'
16
+
17
+ s.rubyforge_project = s.name
18
+ s.license = 'MIT'
19
+
20
+ s.add_dependency "nori", "~> 2.4"
21
+ s.add_dependency "httpi", "~> 2.3"
22
+ s.add_dependency "wasabi", "~> 3.4"
23
+ s.add_dependency "akami", "~> 1.2"
24
+ s.add_dependency "gyoku", "~> 1.2"
25
+ s.add_dependency "builder", ">= 2.1.2"
26
+ s.add_dependency "nokogiri", ">= 1.4.0"
27
+
28
+ s.add_development_dependency "rack"
29
+ s.add_development_dependency "puma", "2.0.0.b4"
30
+
31
+ s.add_development_dependency "rake", "~> 10.1"
32
+ s.add_development_dependency "rspec", "~> 2.14"
33
+ s.add_development_dependency "mocha", "~> 0.14"
34
+ s.add_development_dependency "json", "~> 1.7"
35
+
36
+ ignores = File.readlines(".gitignore").grep(/\S+/).map(&:chomp)
37
+ dotfiles = %w[.gitignore .travis.yml .yardopts]
38
+
39
+ all_files_without_ignores = Dir["**/*"].reject { |f|
40
+ File.directory?(f) || ignores.any? { |i| File.fnmatch(i, f) }
41
+ }
42
+
43
+ s.files = (all_files_without_ignores + dotfiles).sort
44
+
45
+ s.require_path = "lib"
46
+ 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>