savon 0.6.3 → 0.6.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|