savon 0.6.3 → 0.6.4
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 +31 -7
- data/README.textile +0 -0
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/savon.rb +0 -0
- data/lib/savon/client.rb +6 -1
- data/lib/savon/core_ext.rb +0 -0
- data/lib/savon/core_ext/datetime.rb +0 -0
- data/lib/savon/core_ext/hash.rb +0 -0
- data/lib/savon/core_ext/object.rb +0 -0
- data/lib/savon/core_ext/string.rb +0 -0
- data/lib/savon/core_ext/symbol.rb +0 -0
- data/lib/savon/core_ext/uri.rb +0 -0
- data/lib/savon/request.rb +5 -0
- data/lib/savon/response.rb +0 -0
- data/lib/savon/soap.rb +11 -9
- data/lib/savon/wsdl.rb +67 -31
- data/lib/savon/wsse.rb +0 -0
- data/spec/fixtures/multiple_user_response.xml +0 -0
- data/spec/fixtures/soap_fault.xml +0 -0
- data/spec/fixtures/user_fixture.rb +8 -4
- data/spec/fixtures/user_response.xml +0 -0
- data/spec/fixtures/user_wsdl.xml +0 -0
- data/spec/http_stubs.rb +15 -17
- data/spec/savon/client_spec.rb +46 -47
- data/spec/savon/core_ext/datetime_spec.rb +0 -0
- data/spec/savon/core_ext/hash_spec.rb +0 -0
- data/spec/savon/core_ext/object_spec.rb +0 -0
- data/spec/savon/core_ext/string_spec.rb +0 -0
- data/spec/savon/core_ext/symbol_spec.rb +0 -0
- data/spec/savon/core_ext/uri_spec.rb +0 -0
- data/spec/savon/request_spec.rb +44 -64
- data/spec/savon/response_spec.rb +34 -51
- data/spec/savon/savon_spec.rb +13 -19
- data/spec/savon/soap_spec.rb +61 -92
- data/spec/savon/wsdl_spec.rb +19 -34
- data/spec/savon/wsse_spec.rb +42 -58
- data/spec/spec_helper.rb +1 -1
- data/spec/{spec_helper_methods.rb → spec_helper_classes.rb} +32 -4
- metadata +15 -15
data/CHANGELOG
CHANGED
@@ -1,10 +1,34 @@
|
|
1
|
+
== 0.6.4 (2009-12-13)
|
2
|
+
* Refactored specs to be less unit-like.
|
3
|
+
* Added a getter for the Savon::Request to Savon::Client and a read_timeout setter for HTTP requests.
|
4
|
+
* Replaced WSDL document with stream parsing.
|
5
|
+
|
6
|
+
Benchmarks (1000 SOAP calls):
|
7
|
+
|
8
|
+
user system total real
|
9
|
+
0.6.4 72.180000 8.280000 80.460000 (750.799011)
|
10
|
+
0.6.3 192.900000 19.630000 212.530000 (914.031865)
|
11
|
+
|
1
12
|
== 0.6.3 (2009-12-11)
|
2
13
|
* Removing 2 ruby deprecation warnings for parenthesized arguments. (Dave Woodward <dave@futuremint.com>)
|
3
|
-
* Much faster XPath expressions for parsing the WSDL document.
|
4
14
|
* Added global and per request options for disabling Savon::WSDL.
|
5
15
|
|
16
|
+
Benchmarks (1000 SOAP calls):
|
17
|
+
|
18
|
+
user system total real
|
19
|
+
WSDL 192.900000 19.630000 212.530000 (914.031865)
|
20
|
+
disabled WSDL 5.680000 1.340000 7.020000 (298.265318)
|
21
|
+
|
22
|
+
* Improved XPath expressions for parsing the WSDL document.
|
23
|
+
|
24
|
+
Benchmarks (1000 SOAP calls):
|
25
|
+
|
26
|
+
user system total real
|
27
|
+
0.6.3 192.900000 19.630000 212.530000 (914.031865)
|
28
|
+
0.6.2 574.720000 78.380000 653.100000 (1387.778539)
|
29
|
+
|
6
30
|
== 0.6.2 (2009-12-06)
|
7
|
-
*
|
31
|
+
* Added support for changing the name of the SOAP input node.
|
8
32
|
* Added a CHANGELOG.
|
9
33
|
|
10
34
|
== 0.6.1 (2009-12-06)
|
@@ -12,14 +36,14 @@
|
|
12
36
|
|
13
37
|
== 0.6.0 (2009-12-06)
|
14
38
|
* method_missing now yields the SOAP and WSSE objects to a given block.
|
15
|
-
* The response_process (which previously was a block passed to method_missing) was replaced by
|
16
|
-
* Improved SOAP action handling (another problem that came up with
|
39
|
+
* The response_process (which previously was a block passed to method_missing) was replaced by Savon::Response.
|
40
|
+
* Improved SOAP action handling (another problem that came up with issue #1).
|
17
41
|
|
18
42
|
== 0.5.3 (2009-11-30)
|
19
|
-
*
|
43
|
+
* Patch for issue #2 (NoMethodError: undefined method `invalid!' for Savon::WSDL)
|
20
44
|
|
21
45
|
== 0.5.2 (2009-11-30)
|
22
|
-
* Patch for
|
46
|
+
* Patch for issue #1 (Calls fail if api methods have periods in them)
|
23
47
|
|
24
48
|
== 0.5.1 (2009-11-29)
|
25
49
|
* Optimized default response process.
|
@@ -29,4 +53,4 @@
|
|
29
53
|
* Added specs
|
30
54
|
|
31
55
|
== 0.5.0 (2009-11-29)
|
32
|
-
* Complete rewrite.
|
56
|
+
* Complete rewrite.
|
data/README.textile
CHANGED
File without changes
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.6.
|
1
|
+
0.6.4
|
data/lib/savon.rb
CHANGED
File without changes
|
data/lib/savon/client.rb
CHANGED
@@ -23,6 +23,9 @@ module Savon
|
|
23
23
|
# Accessor for Savon::WSDL.
|
24
24
|
attr_accessor :wsdl
|
25
25
|
|
26
|
+
# Returns the Savon::Request.
|
27
|
+
attr_reader :request
|
28
|
+
|
26
29
|
# Returns whether to use Savon::WSDL.
|
27
30
|
def wsdl?
|
28
31
|
self.class.wsdl && @wsdl
|
@@ -47,7 +50,9 @@ module Savon
|
|
47
50
|
# Expects a SOAP action and sets up Savon::SOAP and Savon::WSSE.
|
48
51
|
# Yields them to a given +block+ in case one was given.
|
49
52
|
def setup(soap_action, &block)
|
50
|
-
@soap = SOAP.new
|
53
|
+
@soap = SOAP.new
|
54
|
+
@soap.action = @wsdl.operations[soap_action][:action] if wsdl?
|
55
|
+
@soap.input = @wsdl.operations[soap_action][:input] if wsdl?
|
51
56
|
@wsse = WSSE.new
|
52
57
|
|
53
58
|
yield_parameters &block if block
|
data/lib/savon/core_ext.rb
CHANGED
File without changes
|
File without changes
|
data/lib/savon/core_ext/hash.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/lib/savon/core_ext/uri.rb
CHANGED
File without changes
|
data/lib/savon/request.rb
CHANGED
@@ -45,6 +45,11 @@ module Savon
|
|
45
45
|
# Returns the endpoint URI.
|
46
46
|
attr_reader :endpoint
|
47
47
|
|
48
|
+
# Sets the read timeout for HTTP requests.
|
49
|
+
def read_timeout=(sec)
|
50
|
+
http.read_timeout = sec
|
51
|
+
end
|
52
|
+
|
48
53
|
# Retrieves WSDL document and returns the Net::HTTPResponse.
|
49
54
|
def wsdl
|
50
55
|
log "Retrieving WSDL from: #{@endpoint}"
|
data/lib/savon/response.rb
CHANGED
File without changes
|
data/lib/savon/soap.rb
CHANGED
@@ -29,21 +29,23 @@ module Savon
|
|
29
29
|
|
30
30
|
end
|
31
31
|
|
32
|
-
# Expects a Hash containing the name of the SOAP action and input.
|
33
|
-
def initialize(action = nil)
|
34
|
-
@action = action.kind_of?(Hash) ? action[:name] : ""
|
35
|
-
@input = action.kind_of?(Hash) ? action[:input] : ""
|
36
|
-
end
|
37
|
-
|
38
32
|
# Sets the WSSE options.
|
39
33
|
attr_writer :wsse
|
40
34
|
|
41
35
|
# Accessor for the SOAP action.
|
42
|
-
|
36
|
+
attr_writer :action
|
37
|
+
|
38
|
+
def action
|
39
|
+
@action ||= ""
|
40
|
+
end
|
43
41
|
|
44
42
|
# Accessor for the SOAP input.
|
45
43
|
attr_writer :input
|
46
44
|
|
45
|
+
def input
|
46
|
+
@input ||= ""
|
47
|
+
end
|
48
|
+
|
47
49
|
# Sets the SOAP header. Expected to be a Hash that can be translated
|
48
50
|
# to XML via Hash.to_soap_xml or any other Object responding to to_s.
|
49
51
|
attr_writer :header
|
@@ -102,8 +104,8 @@ module Savon
|
|
102
104
|
# Defaults to use the name of the SOAP action and may be an empty Array
|
103
105
|
# in case the specified SOAP input seems invalid.
|
104
106
|
def input_array
|
105
|
-
return [
|
106
|
-
return [
|
107
|
+
return [input.to_sym] if input && !input.empty?
|
108
|
+
return [action.to_sym] if action && !action.empty?
|
107
109
|
[]
|
108
110
|
end
|
109
111
|
|
data/lib/savon/wsdl.rb
CHANGED
@@ -2,68 +2,104 @@ module Savon
|
|
2
2
|
|
3
3
|
# Savon::WSDL
|
4
4
|
#
|
5
|
-
# Represents
|
5
|
+
# Represents the WSDL document.
|
6
6
|
class WSDL
|
7
7
|
|
8
|
-
#
|
8
|
+
# Initializer, expects a Savon::Request.
|
9
9
|
def initialize(request)
|
10
10
|
@request = request
|
11
11
|
end
|
12
12
|
|
13
|
-
# Returns the namespace URI
|
13
|
+
# Returns the namespace URI of the WSDL.
|
14
14
|
def namespace_uri
|
15
|
-
@namespace_uri ||=
|
15
|
+
@namespace_uri ||= stream.namespace_uri
|
16
16
|
end
|
17
17
|
|
18
|
-
# Returns
|
19
|
-
# and their original names and inputs in another Hash (values).
|
18
|
+
# Returns an Array of available SOAP actions.
|
20
19
|
def soap_actions
|
21
|
-
@soap_actions ||=
|
22
|
-
|
23
|
-
|
20
|
+
@soap_actions ||= stream.operations.keys
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns a Hash of SOAP operations including their corresponding
|
24
|
+
# SOAP actions and inputs.
|
25
|
+
def operations
|
26
|
+
@operations ||= stream.operations
|
24
27
|
end
|
25
28
|
|
26
29
|
# Returns +true+ for available methods and SOAP actions.
|
27
30
|
def respond_to?(method)
|
28
|
-
return true if soap_actions.
|
31
|
+
return true if soap_actions.include? method
|
29
32
|
super
|
30
33
|
end
|
31
34
|
|
32
|
-
# Returns the WSDL document.
|
35
|
+
# Returns the raw WSDL document.
|
33
36
|
def to_s
|
34
|
-
|
37
|
+
@document ||= @request.wsdl.body
|
35
38
|
end
|
36
39
|
|
37
40
|
private
|
38
41
|
|
39
|
-
#
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
raise ArgumentError, "Invalid WSDL: #{@request.endpoint}" if soap_actions.empty?
|
42
|
+
# Returns the Savon::WSDLStream.
|
43
|
+
def stream
|
44
|
+
unless @stream
|
45
|
+
@stream = WSDLStream.new
|
46
|
+
REXML::Document.parse_stream to_s, @stream
|
45
47
|
end
|
46
|
-
@
|
48
|
+
@stream
|
47
49
|
end
|
48
50
|
|
49
|
-
|
50
|
-
|
51
|
-
|
51
|
+
end
|
52
|
+
|
53
|
+
# Savon::WSDLStream
|
54
|
+
#
|
55
|
+
# Stream listener for parsing the WSDL document.
|
56
|
+
class WSDLStream
|
57
|
+
|
58
|
+
# Initializer, sets an empty Hash of operations.
|
59
|
+
def initialize
|
60
|
+
@operations = {}
|
52
61
|
end
|
53
62
|
|
54
|
-
#
|
55
|
-
|
56
|
-
def parse_soap_operations
|
57
|
-
wsdl_binding = document.elements["wsdl:definitions/wsdl:binding"]
|
58
|
-
return {} unless wsdl_binding
|
63
|
+
# Returns the namespace URI from the WSDL document.
|
64
|
+
attr_reader :namespace_uri
|
59
65
|
|
60
|
-
|
61
|
-
|
62
|
-
|
66
|
+
# Returns the SOAP operations found in the WSDL document.
|
67
|
+
attr_reader :operations
|
68
|
+
|
69
|
+
# Hook method called when the stream parser encounters a tag.
|
70
|
+
def tag_start(name, attrs)
|
71
|
+
section_from name
|
72
|
+
@namespace_uri ||= attrs["targetNamespace"] if @section == :definitions
|
73
|
+
operation_from name, attrs if @section == :binding && /.+:operation/ === name
|
74
|
+
end
|
75
|
+
|
76
|
+
# Sets the current section of the WSDL document from a given tag +name+.
|
77
|
+
def section_from(name)
|
78
|
+
section = case name
|
79
|
+
when "wsdl:definitions" then :definitions
|
80
|
+
when "wsdl:types" then :types
|
81
|
+
when "wsdl:message" then :message
|
82
|
+
when "wsdl:portType" then :port_type
|
83
|
+
when "wsdl:binding" then :binding
|
84
|
+
when "wsdl:service" then :service
|
85
|
+
end
|
86
|
+
@section = section if section
|
87
|
+
end
|
63
88
|
|
64
|
-
|
89
|
+
# Stores available operations from a given tag +name+ and +attrs+.
|
90
|
+
def operation_from(name, attrs)
|
91
|
+
if name == "wsdl:operation"
|
92
|
+
@action = attrs["name"]
|
93
|
+
elsif /.+:operation/ === name
|
94
|
+
@action = attrs["soapAction"] if attrs["soapAction"] && !attrs["soapAction"].empty?
|
95
|
+
input = @action.split("/").last
|
96
|
+
@operations[input.snakecase.to_sym] = { :action => @action, :input => input }
|
65
97
|
end
|
66
98
|
end
|
67
99
|
|
100
|
+
# Catches calls to unimplemented hook methods.
|
101
|
+
def method_missing(method, *args)
|
102
|
+
end
|
103
|
+
|
68
104
|
end
|
69
105
|
end
|
data/lib/savon/wsse.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class UserFixture
|
2
2
|
|
3
3
|
@namespace_uri = "http://v1_0.ws.user.example.com"
|
4
|
-
@
|
5
|
-
:user_find_by_id => { :
|
6
|
-
:find_user => { :
|
4
|
+
@operations = {
|
5
|
+
:user_find_by_id => { :action => "User.FindById", :input => "User.FindById" },
|
6
|
+
:find_user => { :action => "findUser", :input => "findUser" }
|
7
7
|
}
|
8
8
|
|
9
9
|
@datetime_string = "2010-11-22T11:22:33"
|
@@ -24,9 +24,13 @@ class UserFixture
|
|
24
24
|
|
25
25
|
class << self
|
26
26
|
|
27
|
-
attr_accessor :namespace_uri, :
|
27
|
+
attr_accessor :namespace_uri, :operations,
|
28
28
|
:datetime_string, :datetime_object, :response_hash
|
29
29
|
|
30
|
+
def soap_actions
|
31
|
+
@operations.keys
|
32
|
+
end
|
33
|
+
|
30
34
|
def user_wsdl
|
31
35
|
load_fixture :user_wsdl
|
32
36
|
end
|
File without changes
|
data/spec/fixtures/user_wsdl.xml
CHANGED
File without changes
|
data/spec/http_stubs.rb
CHANGED
@@ -2,24 +2,22 @@ require "fakeweb"
|
|
2
2
|
|
3
3
|
FakeWeb.allow_net_connect = false
|
4
4
|
|
5
|
-
#
|
6
|
-
FakeWeb.register_uri :get,
|
7
|
-
FakeWeb.register_uri :post,
|
5
|
+
# Some WSDL and SOAP request.
|
6
|
+
FakeWeb.register_uri :get, EndpointHelper.wsdl_endpoint, :body => UserFixture.user_wsdl
|
7
|
+
FakeWeb.register_uri :post, EndpointHelper.soap_endpoint, :body => UserFixture.user_response
|
8
8
|
|
9
|
-
#
|
10
|
-
FakeWeb.register_uri :get,
|
11
|
-
FakeWeb.register_uri :post,
|
9
|
+
# WSDL and SOAP request with multiple "//return" nodes.
|
10
|
+
FakeWeb.register_uri :get, EndpointHelper.wsdl_endpoint(:multiple), :body => UserFixture.user_wsdl
|
11
|
+
FakeWeb.register_uri :post, EndpointHelper.soap_endpoint(:multiple), :body => UserFixture.multiple_user_response
|
12
12
|
|
13
|
-
#
|
14
|
-
FakeWeb.register_uri :get,
|
15
|
-
FakeWeb.register_uri :post,
|
13
|
+
# WSDL and SOAP request with a Savon::SOAPFault.
|
14
|
+
FakeWeb.register_uri :get, EndpointHelper.wsdl_endpoint(:soap_fault), :body => UserFixture.user_wsdl
|
15
|
+
FakeWeb.register_uri :post, EndpointHelper.soap_endpoint(:soap_fault), :body => UserFixture.soap_fault
|
16
16
|
|
17
|
-
#
|
18
|
-
FakeWeb.register_uri :get,
|
19
|
-
FakeWeb.register_uri :post,
|
20
|
-
:status => ["404", "Not Found"]
|
17
|
+
# WSDL and SOAP request with a Savon::HTTPError.
|
18
|
+
FakeWeb.register_uri :get, EndpointHelper.wsdl_endpoint(:http_error), :body => UserFixture.user_wsdl
|
19
|
+
FakeWeb.register_uri :post, EndpointHelper.soap_endpoint(:http_error), :body => "", :status => ["404", "Not Found"]
|
21
20
|
|
22
|
-
#
|
23
|
-
FakeWeb.register_uri :get,
|
24
|
-
FakeWeb.register_uri :post,
|
25
|
-
:status => ["404", "Not Found"]
|
21
|
+
# WSDL and SOAP request with an invalid endpoint.
|
22
|
+
FakeWeb.register_uri :get, EndpointHelper.wsdl_endpoint(:invalid), :body => ""
|
23
|
+
FakeWeb.register_uri :post, EndpointHelper.soap_endpoint(:invalid), :body => "", :status => ["404", "Not Found"]
|
data/spec/savon/client_spec.rb
CHANGED
@@ -1,69 +1,68 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Savon::Client do
|
4
|
-
before { @client =
|
4
|
+
before { @client = Savon::Client.new EndpointHelper.wsdl_endpoint }
|
5
5
|
|
6
|
-
|
7
|
-
Savon::Client.new
|
6
|
+
it "is initialized with a SOAP endpoint String" do
|
7
|
+
Savon::Client.new EndpointHelper.wsdl_endpoint
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
10
|
+
it "raises an ArgumentError when initialized with an invalid endpoint" do
|
11
|
+
lambda { Savon::Client.new "invalid" }.should raise_error ArgumentError
|
12
|
+
end
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
end
|
14
|
+
it "has a getter for accessing the Savon::WSDL" do
|
15
|
+
@client.wsdl.should be_a Savon::WSDL
|
18
16
|
end
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
@client.wsdl.should be_a Savon::WSDL
|
23
|
-
end
|
18
|
+
it "has a getter for accessing the Savon::Request" do
|
19
|
+
@client.request.should be_a Savon::Request
|
24
20
|
end
|
25
21
|
|
26
|
-
|
27
|
-
|
28
|
-
@client.respond_to?(UserFixture.soap_actions.keys.first).
|
29
|
-
should be_true
|
30
|
-
end
|
22
|
+
it "has a getter for returning whether to use the Savon::WSDL (global setting)" do
|
23
|
+
@client.wsdl?.should be_true
|
31
24
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
25
|
+
Savon::Client.wsdl = false
|
26
|
+
@client.wsdl?.should be_false
|
27
|
+
Savon::Client.wsdl = true
|
28
|
+
|
29
|
+
@client.wsdl = false
|
30
|
+
@client.wsdl?.should be_false
|
36
31
|
end
|
37
32
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
33
|
+
it "responds to SOAP actions while still behaving as usual otherwise" do
|
34
|
+
@client.respond_to?(UserFixture.soap_actions.first).should be_true
|
35
|
+
@client.respond_to?(:object_id).should be_true
|
36
|
+
@client.respond_to?(:some_undefined_method).should be_false
|
37
|
+
end
|
42
38
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
39
|
+
it "dispatches SOAP calls via method_missing and returns the Savon::Response" do
|
40
|
+
@client.find_user.should be_a Savon::Response
|
41
|
+
end
|
47
42
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
43
|
+
it "raises a Savon::SOAPFault in case of a SOAP fault" do
|
44
|
+
client = Savon::Client.new EndpointHelper.wsdl_endpoint(:soap_fault)
|
45
|
+
lambda { client.find_user }.should raise_error Savon::SOAPFault
|
46
|
+
end
|
52
47
|
|
53
|
-
|
54
|
-
|
55
|
-
|
48
|
+
it "raises a Savon::HTTPError in case of an HTTP error" do
|
49
|
+
client = Savon::Client.new EndpointHelper.wsdl_endpoint(:http_error)
|
50
|
+
lambda { client.find_user }.should raise_error Savon::HTTPError
|
51
|
+
end
|
56
52
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
wsse.should be_a Savon::WSSE
|
61
|
-
end
|
62
|
-
end
|
53
|
+
it "yields the SOAP object to a block when it expects one argument" do
|
54
|
+
@client.find_user { |soap| soap.should be_a Savon::SOAP }
|
55
|
+
end
|
63
56
|
|
64
|
-
|
65
|
-
|
57
|
+
it "yields the SOAP and WSSE object to a block when it expects two argument" do
|
58
|
+
@client.find_user do |soap, wsse|
|
59
|
+
soap.should be_a Savon::SOAP
|
60
|
+
wsse.should be_a Savon::WSSE
|
66
61
|
end
|
67
62
|
end
|
68
63
|
|
69
|
-
|
64
|
+
it "still raises a NoMethodError for undefined methods" do
|
65
|
+
lambda { @client.some_undefined_method }.should raise_error NoMethodError
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|