savon 0.3.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/README.textile +68 -0
  2. data/Rakefile +9 -7
  3. data/VERSION +1 -1
  4. data/lib/savon.rb +33 -34
  5. data/lib/savon/client.rb +96 -0
  6. data/lib/savon/core_ext.rb +6 -0
  7. data/lib/savon/core_ext/datetime.rb +8 -0
  8. data/lib/savon/core_ext/hash.rb +65 -0
  9. data/lib/savon/core_ext/object.rb +14 -0
  10. data/lib/savon/core_ext/string.rb +41 -0
  11. data/lib/savon/core_ext/symbol.rb +8 -0
  12. data/lib/savon/core_ext/uri.rb +10 -0
  13. data/lib/savon/request.rb +103 -0
  14. data/lib/savon/soap.rb +71 -0
  15. data/lib/savon/validation.rb +57 -0
  16. data/lib/savon/wsdl.rb +39 -41
  17. data/lib/savon/wsse.rb +111 -0
  18. data/spec/fixtures/multiple_user_response.xml +22 -0
  19. data/spec/fixtures/soap_fault.xml +0 -0
  20. data/spec/fixtures/user_fixture.rb +42 -0
  21. data/spec/fixtures/user_response.xml +4 -2
  22. data/spec/fixtures/user_wsdl.xml +0 -0
  23. data/spec/http_stubs.rb +20 -0
  24. data/spec/savon/client_spec.rb +144 -0
  25. data/spec/savon/core_ext/datetime_spec.rb +12 -0
  26. data/spec/savon/core_ext/hash_spec.rb +146 -0
  27. data/spec/savon/core_ext/object_spec.rb +26 -0
  28. data/spec/savon/core_ext/string_spec.rb +52 -0
  29. data/spec/savon/core_ext/symbol_spec.rb +11 -0
  30. data/spec/savon/core_ext/uri_spec.rb +15 -0
  31. data/spec/savon/request_spec.rb +93 -0
  32. data/spec/savon/savon_spec.rb +37 -0
  33. data/spec/savon/soap_spec.rb +101 -0
  34. data/spec/savon/validation_spec.rb +88 -0
  35. data/spec/savon/wsdl_spec.rb +17 -46
  36. data/spec/savon/wsse_spec.rb +169 -0
  37. data/spec/spec_helper.rb +7 -92
  38. data/spec/spec_helper_methods.rb +29 -0
  39. metadata +68 -20
  40. data/README.rdoc +0 -62
  41. data/lib/savon/service.rb +0 -151
  42. data/spec/savon/service_spec.rb +0 -76
@@ -1,100 +1,15 @@
1
1
  require "rubygems"
2
2
  gem "rspec", ">= 1.2.8"
3
3
  require "spec"
4
- require "rr"
5
- require File.join(File.dirname(__FILE__), "..", "lib", "savon")
4
+ require "mocha"
6
5
 
7
6
  Spec::Runner.configure do |config|
8
- config.mock_with :rr
7
+ config.mock_with :mocha
9
8
  end
10
9
 
11
- module SpecHelper
12
- def some_url
13
- "http://example.com"
14
- end
10
+ require "savon"
11
+ Savon::Request.log = false
15
12
 
16
- def some_uri
17
- URI(some_url)
18
- end
19
-
20
- def some_http
21
- Net::HTTP.new(some_uri.host, some_uri.port)
22
- end
23
-
24
- def new_wsdl
25
- Savon::WSDL.new(some_uri, UserFixture.http_mock)
26
- end
27
-
28
- def new_service_instance(options = {})
29
- service = Savon::Service.new(some_url)
30
- service.instance_variable_set("@http", UserFixture.http_mock(options))
31
- service
32
- end
33
- end
34
-
35
- class UserFixture
36
- extend RR::Adapters::RRMethods
37
-
38
- class << self
39
- include SpecHelper
40
-
41
- def namespace_uri
42
- "http://v1_0.ws.user.example.com"
43
- end
44
-
45
- def soap_actions
46
- %w(findUser)
47
- end
48
-
49
- def choice_elements
50
- %w(idCredential emailCredential)
51
- end
52
-
53
- def user_wsdl
54
- load_fixture("user_wsdl.xml")
55
- end
56
-
57
- def user_response
58
- load_fixture("user_response.xml")
59
- end
60
-
61
- def soap_fault
62
- load_fixture("soap_fault.xml")
63
- end
64
-
65
- def http_mock(options = {})
66
- response_body = options[:soap_fault] ? soap_fault : user_response
67
- response_code = options[:http_error] ? 500 : 200
68
- response_body = "" if options[:http_error] && !options[:soap_fault]
69
- generate_http_mock(soap_response_mock(response_body, response_code))
70
- end
71
-
72
- private
73
-
74
- def load_fixture(file)
75
- file_path = File.join(File.dirname(__FILE__), "fixtures", file)
76
- IO.readlines(file_path, "").to_s
77
- end
78
-
79
- def generate_http_mock(soap_response)
80
- mock = some_http
81
- stub(mock).get(anything) { wsdl_response_mock(user_wsdl) }
82
- stub(mock).request_post(anything, anything, anything) { soap_response }
83
- mock
84
- end
85
-
86
- def wsdl_response_mock(response_body)
87
- mock = mock()
88
- stub(mock).body { response_body }
89
- mock
90
- end
91
-
92
- def soap_response_mock(response_body, response_code)
93
- mock = mock()
94
- stub(mock).body { response_body }
95
- stub(mock).code { response_code }
96
- stub(mock).message { "whatever" }
97
- mock
98
- end
99
- end
100
- end
13
+ require "fixtures/user_fixture"
14
+ require "spec_helper_methods"
15
+ require "http_stubs"
@@ -0,0 +1,29 @@
1
+ class SpecHelper
2
+
3
+ @soap_call_endpoint = "http://services.example.com/UserService"
4
+ @some_endpoint = @soap_call_endpoint + "?wsdl"
5
+ @some_endpoint_uri = URI @some_endpoint
6
+
7
+ @soap_multiple_endpoint = "http://multiple.example.com/UserService"
8
+ @multiple_endpoint = @soap_multiple_endpoint + "?wsdl"
9
+
10
+ @soap_soapfault_endpoint = "http://soapfault.example.com/UserService"
11
+ @soapfault_endpoint = @soap_soapfault_endpoint + "?wsdl"
12
+
13
+ @soap_httperror_endpoint = "http://httperror.example.com/UserService"
14
+ @httperror_endpoint = @soap_httperror_endpoint + "?wsdl"
15
+
16
+ @wsse_security_nodes = ["wsse:Security", "wsse:UsernameToken",
17
+ "wsse:Username", "wsse:Password", "wsse:Nonce", "wsu:Created"]
18
+
19
+ class << self
20
+
21
+ attr_accessor :soap_call_endpoint, :some_endpoint, :some_endpoint_uri,
22
+ :soap_multiple_endpoint , :multiple_endpoint,
23
+ :soap_soapfault_endpoint, :soapfault_endpoint,
24
+ :soap_httperror_endpoint, :httperror_endpoint,
25
+ :wsse_security_nodes
26
+
27
+ end
28
+
29
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: savon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Harrington
@@ -9,28 +9,28 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-23 00:00:00 +01:00
12
+ date: 2009-11-29 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: hpricot
16
+ name: builder
17
17
  type: :runtime
18
18
  version_requirement:
19
19
  version_requirements: !ruby/object:Gem::Requirement
20
20
  requirements:
21
- - - "="
21
+ - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 0.8.241
23
+ version: 2.1.2
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
- name: apricoteatsgorilla
26
+ name: crack
27
27
  type: :runtime
28
28
  version_requirement:
29
29
  version_requirements: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "="
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.5.13
33
+ version: 0.1.4
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: rspec
@@ -43,36 +43,72 @@ dependencies:
43
43
  version: 1.2.8
44
44
  version:
45
45
  - !ruby/object:Gem::Dependency
46
- name: rr
46
+ name: mocha
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.7
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: fakeweb
47
57
  type: :development
48
58
  version_requirement:
49
59
  version_requirements: !ruby/object:Gem::Requirement
50
60
  requirements:
51
61
  - - ">="
52
62
  - !ruby/object:Gem::Version
53
- version: 0.10.0
63
+ version: 1.2.7
54
64
  version:
55
- description: SOAP client library to enjoy
65
+ description: Heavy metal Ruby SOAP client library
56
66
  email: me@rubiii.com
57
67
  executables: []
58
68
 
59
69
  extensions: []
60
70
 
61
71
  extra_rdoc_files:
62
- - README.rdoc
72
+ - README.textile
63
73
  files:
64
- - README.rdoc
74
+ - README.textile
65
75
  - Rakefile
66
76
  - VERSION
67
77
  - lib/savon.rb
68
- - lib/savon/service.rb
78
+ - lib/savon/client.rb
79
+ - lib/savon/core_ext.rb
80
+ - lib/savon/core_ext/datetime.rb
81
+ - lib/savon/core_ext/hash.rb
82
+ - lib/savon/core_ext/object.rb
83
+ - lib/savon/core_ext/string.rb
84
+ - lib/savon/core_ext/symbol.rb
85
+ - lib/savon/core_ext/uri.rb
86
+ - lib/savon/request.rb
87
+ - lib/savon/soap.rb
88
+ - lib/savon/validation.rb
69
89
  - lib/savon/wsdl.rb
90
+ - lib/savon/wsse.rb
91
+ - spec/fixtures/multiple_user_response.xml
70
92
  - spec/fixtures/soap_fault.xml
93
+ - spec/fixtures/user_fixture.rb
71
94
  - spec/fixtures/user_response.xml
72
95
  - spec/fixtures/user_wsdl.xml
73
- - spec/savon/service_spec.rb
96
+ - spec/http_stubs.rb
97
+ - spec/savon/client_spec.rb
98
+ - spec/savon/core_ext/datetime_spec.rb
99
+ - spec/savon/core_ext/hash_spec.rb
100
+ - spec/savon/core_ext/object_spec.rb
101
+ - spec/savon/core_ext/string_spec.rb
102
+ - spec/savon/core_ext/symbol_spec.rb
103
+ - spec/savon/core_ext/uri_spec.rb
104
+ - spec/savon/request_spec.rb
105
+ - spec/savon/savon_spec.rb
106
+ - spec/savon/soap_spec.rb
107
+ - spec/savon/validation_spec.rb
74
108
  - spec/savon/wsdl_spec.rb
109
+ - spec/savon/wsse_spec.rb
75
110
  - spec/spec_helper.rb
111
+ - spec/spec_helper_methods.rb
76
112
  has_rdoc: true
77
113
  homepage: http://github.com/rubiii/savon
78
114
  licenses: []
@@ -82,8 +118,6 @@ rdoc_options:
82
118
  - --charset=UTF-8
83
119
  - --title
84
120
  - Savon
85
- - --main
86
- - README.rdoc
87
121
  - --line-numbers
88
122
  - --inline-source
89
123
  require_paths:
@@ -106,8 +140,22 @@ rubyforge_project:
106
140
  rubygems_version: 1.3.5
107
141
  signing_key:
108
142
  specification_version: 3
109
- summary: SOAP client library to enjoy
143
+ summary: Heavy metal Ruby SOAP client library
110
144
  test_files:
111
- - spec/spec_helper.rb
112
- - spec/savon/service_spec.rb
145
+ - spec/fixtures/user_fixture.rb
146
+ - spec/http_stubs.rb
147
+ - spec/savon/client_spec.rb
148
+ - spec/savon/core_ext/datetime_spec.rb
149
+ - spec/savon/core_ext/hash_spec.rb
150
+ - spec/savon/core_ext/object_spec.rb
151
+ - spec/savon/core_ext/string_spec.rb
152
+ - spec/savon/core_ext/symbol_spec.rb
153
+ - spec/savon/core_ext/uri_spec.rb
154
+ - spec/savon/request_spec.rb
155
+ - spec/savon/savon_spec.rb
156
+ - spec/savon/soap_spec.rb
157
+ - spec/savon/validation_spec.rb
113
158
  - spec/savon/wsdl_spec.rb
159
+ - spec/savon/wsse_spec.rb
160
+ - spec/spec_helper.rb
161
+ - spec/spec_helper_methods.rb
@@ -1,62 +0,0 @@
1
- = Savon
2
-
3
- Savon::Service is a SOAP client library to enjoy. The goal is to minimize
4
- the overhead of working with SOAP services and provide a lightweight
5
- alternative to other libraries.
6
-
7
- == Install
8
-
9
- The gem for Savon is in the {gemcutter}[http://gemcutter.org] repository.
10
- Please follow the steps on their website to set up your rubygems installation.
11
- Afterwards you can install the gem like this:
12
-
13
- $ gem install savon
14
-
15
- == Dependencies
16
-
17
- rubiii-apricoteatsgorilla >= 0.5.10
18
- hpricot 0.8.241 (the latest JRuby-compatible version)
19
-
20
- Hpricot 0.8.241 is also available at: {Apricot eats Gorilla Downloads}[http://github.com/rubiii/apricoteatsgorilla/downloads]
21
-
22
- == How to use
23
-
24
- Instantiate a new Savon::Service instance passing in the WSDL of your service.
25
-
26
- proxy = Savon::Service.new("http://example.com/ExampleService?wsdl")
27
-
28
- Call the SOAP service method of your choice on your Savon::Service instance.
29
-
30
- response = proxy.get_all_users
31
-
32
- Or pass in a Hash of options for the SOAP service to receive.
33
-
34
- response = proxy.find_user_by_id(:id => 123)
35
-
36
- Or specify a custom XPath-Expression to start translating the SOAP response at.
37
- By default the response is translated starting at "//return".
38
-
39
- response = proxy.find_user_by_id(nil, "//user/email")
40
-
41
- === Check for available SOAP actions
42
-
43
- Access the WSDL to get an Array of SOAP actions found in the WSDL document.
44
-
45
- proxy.wsdl.soap_actions
46
- # => [ "getAllUsers", "findUserById" ]
47
-
48
- === Handle HTTP error and SOAP faults
49
-
50
- Savon::Service raises a Savon::SOAPFault in case of a SOAP fault and a
51
- Savon::HTTPError in case of an HTTP error.
52
-
53
- === Logging request and response
54
-
55
- You should specify the logger to use before working with any service.
56
-
57
- # example for Ruby on Rails
58
- Savon.logger = RAILS_DEFAULT_LOGGER
59
-
60
- Of course you can also specify the log level if needed. By default it's set to :debug.
61
-
62
- Savon.log_level = :info
@@ -1,151 +0,0 @@
1
- module Savon
2
-
3
- # == Savon::Service
4
- #
5
- # Savon::Service is a SOAP client library to enjoy. The goal is to minimize
6
- # the overhead of working with SOAP services and provide a lightweight
7
- # alternative to other libraries.
8
- #
9
- # ==== Example
10
- #
11
- # proxy = Savon::Service.new("http://example.com/ExampleService?wsdl")
12
- # response = proxy.find_user_by_id(:id => 123)
13
- class Service
14
-
15
- # Supported SOAP versions.
16
- SOAPVersions = [1, 2]
17
-
18
- # Content-Types by SOAP version.
19
- ContentType = { 1 => "text/xml", 2 => "application/soap+xml" }
20
-
21
- # Accessor for the WSSE username.
22
- attr_accessor :wsse_username
23
-
24
- # Accessor for the WSSE password.
25
- attr_accessor :wsse_password
26
-
27
- # Sets whether the WSSE password should be encrypted.
28
- attr_writer :wsse_digest
29
-
30
- # Sets whether the response should be returned as is.
31
- attr_writer :pure_response
32
-
33
- # Initializer expects an +endpoint+ URI and takes an optional SOAP +version+.
34
- def initialize(endpoint, version = 1)
35
- raise ArgumentError, "Invalid endpoint: #{endpoint}" unless /^http.+/ === endpoint
36
- raise ArgumentError, "Invalid version: #{version}" unless SOAPVersions.include? version
37
- @endpoint = URI(endpoint)
38
- @version = version
39
- @ssl = /^https.+/ === endpoint
40
- end
41
-
42
- # Returns an instance of Savon::WSDL.
43
- def wsdl
44
- @wsdl ||= WSDL.new(@endpoint, http)
45
- end
46
-
47
- # Returns whether the WSSE password should be encrypted. Defaults to +false+.
48
- def wsse_digest?
49
- @wsse_digest == true
50
- end
51
-
52
- # Returns whether the response should be returned as is. Defaults to +false+.
53
- def pure_response?
54
- @pure_response == true
55
- end
56
-
57
- private
58
-
59
- # Dispatches a SOAP request, handles any HTTP errors and SOAP faults
60
- # and returns the SOAP response.
61
- def dispatch(soap_action, soap_body, response_xpath)
62
- ApricotEatsGorilla.nodes_to_namespace = { :wsdl => wsdl.choice_elements }
63
- headers, body = build_request_parameters(soap_action, soap_body)
64
-
65
- Savon.log("SOAP request: #{@endpoint}")
66
- Savon.log(headers.map { |k, v| "#{k}: #{v}" }.join(", "))
67
- Savon.log(body)
68
-
69
- response = http.request_post(@endpoint.path, body, headers)
70
-
71
- Savon.log("SOAP response (status #{response.code}):")
72
- Savon.log(response.body)
73
-
74
- soap_fault = ApricotEatsGorilla[response.body, "//soap:Fault"]
75
- raise_soap_fault(soap_fault) if soap_fault && !soap_fault.empty?
76
- raise_http_error(response) if response.code.to_i >= 300
77
-
78
- if pure_response?
79
- response.body
80
- else
81
- ApricotEatsGorilla[response.body, response_xpath]
82
- end
83
- end
84
-
85
- # Expects the requested +soap_action+ and +soap_body+ and builds and
86
- # returns the request header and body to dispatch a SOAP request.
87
- def build_request_parameters(soap_action, soap_body)
88
- headers = { "Content-Type" => ContentType[@version], "SOAPAction" => soap_action }
89
- namespaces = { "xmlns:wsdl" => wsdl.namespace_uri }
90
-
91
- body = ApricotEatsGorilla.soap_envelope(namespaces, wsse, @version) do
92
- ApricotEatsGorilla["wsdl:#{soap_action}" => soap_body]
93
- end
94
- [headers, body]
95
- end
96
-
97
- # Returns the WSSE arguments if :wsse_username and :wsse_password are set.
98
- def wsse
99
- if @wsse_username && @wsse_password
100
- { :username => @wsse_username, :password => @wsse_password, :digest => wsse_digest? }
101
- else
102
- nil
103
- end
104
- end
105
-
106
- # Expects a Hash containing information about a SOAP fault and raises
107
- # a Savon::SOAPFault.
108
- def raise_soap_fault(soap_fault)
109
- message = case @version
110
- when 1
111
- "#{soap_fault[:faultcode]}: #{soap_fault[:faultstring]}"
112
- else
113
- "#{soap_fault[:code][:value]}: #{soap_fault[:reason][:text]}"
114
- end
115
- raise SOAPFault, message
116
- end
117
-
118
- # Expects a Net::HTTPResponse and raises a Savon::HTTPError.
119
- def raise_http_error(response)
120
- raise HTTPError, "#{response.message} (#{response.code}): #{response.body}"
121
- end
122
-
123
- # Returns a Net::HTTP instance.
124
- def http
125
- unless @http
126
- @http ||= Net::HTTP.new(@endpoint.host, @endpoint.port)
127
- @http.use_ssl = true if @ssl
128
- end
129
- @http
130
- end
131
-
132
- # Catches calls to SOAP actions, checks if the method called was found in
133
- # the WSDL and dispatches the SOAP action if it's valid. Takes an optional
134
- # Hash of options to be passed to the SOAP action and an optional XPath-
135
- # Expression to define a custom XML root node to start parsing the SOAP
136
- # response at.
137
- def method_missing(method, *args)
138
- soap_action = camelize(method)
139
- super unless wsdl.soap_actions.include? soap_action
140
- soap_body = args[0] || {}
141
- response_xpath = args[1] || "//return"
142
- dispatch(soap_action, soap_body, response_xpath)
143
- end
144
-
145
- # Converts a given +string+ from snake_case to lowerCamelCase.
146
- def camelize(string)
147
- string.to_s.gsub(/_(.)/) { $1.upcase } if string
148
- end
149
-
150
- end
151
- end