actionwebservice 0.5.0 → 0.6.0
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 → CHANGELOG} +20 -0
- data/README +45 -1
- data/Rakefile +12 -10
- data/TODO +8 -9
- data/lib/action_web_service.rb +10 -6
- data/lib/action_web_service/api.rb +1 -2
- data/lib/action_web_service/api/{abstract.rb → base.rb} +14 -71
- data/lib/action_web_service/base.rb +0 -3
- data/lib/action_web_service/client/base.rb +1 -12
- data/lib/action_web_service/client/soap_client.rb +49 -17
- data/lib/action_web_service/client/xmlrpc_client.rb +20 -15
- data/lib/action_web_service/container.rb +3 -85
- data/lib/action_web_service/{api/action_controller.rb → container/action_controller_container.rb} +2 -2
- data/lib/action_web_service/container/delegated_container.rb +87 -0
- data/lib/action_web_service/container/direct_container.rb +70 -0
- data/lib/action_web_service/dispatcher/abstract.rb +100 -102
- data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +199 -137
- data/lib/action_web_service/protocol.rb +1 -1
- data/lib/action_web_service/protocol/abstract.rb +14 -112
- data/lib/action_web_service/protocol/discovery.rb +37 -0
- data/lib/action_web_service/protocol/soap_protocol.rb +32 -458
- data/lib/action_web_service/protocol/xmlrpc_protocol.rb +29 -149
- data/lib/action_web_service/struct.rb +2 -5
- data/lib/action_web_service/test_invoke.rb +130 -0
- data/lib/action_web_service/vendor/ws.rb +4 -0
- data/lib/action_web_service/vendor/ws/common.rb +8 -0
- data/lib/action_web_service/vendor/ws/encoding.rb +3 -0
- data/lib/action_web_service/vendor/ws/encoding/abstract.rb +26 -0
- data/lib/action_web_service/vendor/ws/encoding/soap_rpc_encoding.rb +90 -0
- data/lib/action_web_service/vendor/ws/encoding/xmlrpc_encoding.rb +53 -0
- data/lib/action_web_service/vendor/ws/marshaling.rb +3 -0
- data/lib/action_web_service/vendor/ws/marshaling/abstract.rb +17 -0
- data/lib/action_web_service/vendor/ws/marshaling/soap_marshaling.rb +277 -0
- data/lib/action_web_service/vendor/ws/marshaling/xmlrpc_marshaling.rb +116 -0
- data/lib/action_web_service/vendor/ws/types.rb +162 -0
- data/test/abstract_client.rb +8 -11
- data/test/abstract_dispatcher.rb +370 -0
- data/test/abstract_unit.rb +1 -0
- data/test/api_test.rb +18 -1
- data/test/apis/auto_load_api.rb +3 -0
- data/test/apis/broken_auto_load_api.rb +2 -0
- data/test/client_soap_test.rb +16 -3
- data/test/client_xmlrpc_test.rb +16 -4
- data/test/container_test.rb +28 -8
- data/test/dispatcher_action_controller_soap_test.rb +106 -0
- data/test/dispatcher_action_controller_xmlrpc_test.rb +44 -0
- data/test/gencov +1 -1
- data/test/invocation_test.rb +39 -3
- data/test/run +4 -4
- data/test/test_invoke_test.rb +77 -0
- data/test/ws/abstract_encoding.rb +68 -0
- data/test/ws/abstract_unit.rb +13 -0
- data/test/ws/gencov +3 -0
- data/test/ws/run +5 -0
- data/test/ws/soap_marshaling_test.rb +91 -0
- data/test/ws/soap_rpc_encoding_test.rb +47 -0
- data/test/ws/types_test.rb +41 -0
- data/test/ws/xmlrpc_encoding_test.rb +34 -0
- metadata +48 -19
- data/lib/action_web_service/protocol/registry.rb +0 -55
- data/lib/action_web_service/support/signature.rb +0 -100
- data/test/abstract_soap.rb +0 -58
- data/test/dispatcher_action_controller_test.rb +0 -186
- data/test/protocol_registry_test.rb +0 -53
- data/test/protocol_soap_test.rb +0 -252
- data/test/protocol_xmlrpc_test.rb +0 -147
data/{ChangeLog → CHANGELOG}
RENAMED
@@ -1,3 +1,23 @@
|
|
1
|
+
*0.6.0* (7th March, 2005)
|
2
|
+
|
3
|
+
* Add action_controller/test_invoke, used for integrating AWS with the Rails testing infrastructure
|
4
|
+
|
5
|
+
* Allow passing through options to the SOAP RPC driver for the SOAP client
|
6
|
+
|
7
|
+
* Make the SOAP WS marshaler use #columns to decide which fields to marshal as well, avoids providing attributes brought in by associations
|
8
|
+
|
9
|
+
* Add <tt>ActionWebService::API::Base.allow_active_record_expects</tt> option, with a default of false. Setting this to true will allow specifying ActiveRecord::Base model classes in <tt>:expects</tt>. API writers should take care to validate the received ActiveRecord model objects when turning it on, and/or have an authentication mechanism in place to reduce the security risk.
|
10
|
+
|
11
|
+
* Improve error message reporting. Bugs in either AWS or the web service itself will send back a protocol-specific error report message if possible, otherwise, provide as much detail as possible.
|
12
|
+
|
13
|
+
* Removed type checking of received parameters, and perform casting for XML-RPC if possible, but fallback to the received parameters if casting fails, closes #677
|
14
|
+
|
15
|
+
* Refactored SOAP and XML-RPC marshaling and encoding into a small library devoted exclusively to protocol specifics, also cleaned up the SOAP marshaling approach, so that array and custom type marshaling should be a bit faster.
|
16
|
+
|
17
|
+
* Add namespaced XML-RPC method name support, closes #678
|
18
|
+
|
19
|
+
* Replace '::' with '..' in fully qualified type names for marshaling and WSDL. This improves interoperability with .NET, and closes #676.
|
20
|
+
|
1
21
|
*0.5.0* (24th February, 2005)
|
2
22
|
|
3
23
|
* lib/action_service/dispatcher*: replace "router" fragments with
|
data/README
CHANGED
@@ -114,7 +114,7 @@ For this example, protocol requests for +Add+ and +Remove+ methods sent to
|
|
114
114
|
=== Delegated dispatching
|
115
115
|
|
116
116
|
This mode can be turned on by setting the +web_service_dispatching_mode+ option
|
117
|
-
in a controller
|
117
|
+
in a controller to <tt>:delegated</tt>.
|
118
118
|
|
119
119
|
In this mode, the controller contains one or more web service objects (objects
|
120
120
|
that implement an ActionWebService::API::Base definition). These web service
|
@@ -153,6 +153,50 @@ Other controller actions (actions that aren't the target of a +web_service+ call
|
|
153
153
|
are ignored for ActionWebService purposes, and can do normal action tasks.
|
154
154
|
|
155
155
|
|
156
|
+
=== Layered dispatching
|
157
|
+
|
158
|
+
This mode can be turned on by setting the +web_service_dispatching_mode+ option
|
159
|
+
in a controller to <tt>:layered</tt>.
|
160
|
+
|
161
|
+
This mode is similar to _delegated_ mode, in that multiple web service objects
|
162
|
+
can be attached to one controller, however, all protocol requests are sent to a
|
163
|
+
single endpoint.
|
164
|
+
|
165
|
+
This mode is only usable by XML-RPC. In this mode, method names can contain
|
166
|
+
_prefixes_, which will indicate which web service object implements the API
|
167
|
+
identified by that prefix.
|
168
|
+
|
169
|
+
The _prefix_ can be any word, followed by a period.
|
170
|
+
|
171
|
+
==== Layered dispatching example
|
172
|
+
|
173
|
+
|
174
|
+
class ApiController < ApplicationController
|
175
|
+
web_service_dispatching_mode :layered
|
176
|
+
|
177
|
+
web_service :mt, MovableTypeService.new
|
178
|
+
web_service :blogger, BloggerService.new
|
179
|
+
web_service :metaWeblog, MetaWeblogService.new
|
180
|
+
end
|
181
|
+
|
182
|
+
class MovableTypeService < ActionWebService::Base
|
183
|
+
...
|
184
|
+
end
|
185
|
+
|
186
|
+
class BloggerService < ActionWebService::Base
|
187
|
+
...
|
188
|
+
end
|
189
|
+
|
190
|
+
class MetaWeblogService < ActionWebService::API::Base
|
191
|
+
...
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
For this example, a remote call for a method with a name like
|
196
|
+
<tt>mt.getCategories</tt> will be dispatched as the <tt>getCategories</tt>
|
197
|
+
method on the <tt>:mt</tt> service.
|
198
|
+
|
199
|
+
|
156
200
|
== Using the client support
|
157
201
|
|
158
202
|
Action Web Service includes client classes that can use the same API
|
data/Rakefile
CHANGED
@@ -9,7 +9,7 @@ require 'fileutils'
|
|
9
9
|
|
10
10
|
PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
|
11
11
|
PKG_NAME = 'actionwebservice'
|
12
|
-
PKG_VERSION = '0.
|
12
|
+
PKG_VERSION = '0.6.0' + PKG_BUILD
|
13
13
|
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
14
14
|
PKG_DESTINATION = ENV["RAILS_PKG_DESTINATION"] || "../#{PKG_NAME}"
|
15
15
|
|
@@ -20,7 +20,7 @@ task :default => [ :test ]
|
|
20
20
|
# Run the unit tests
|
21
21
|
Rake::TestTask.new { |t|
|
22
22
|
t.libs << "test"
|
23
|
-
t.
|
23
|
+
t.test_files = Dir['test/*_test.rb'] + Dir['test/ws/*_test.rb']
|
24
24
|
t.verbose = true
|
25
25
|
}
|
26
26
|
|
@@ -31,12 +31,14 @@ Rake::RDocTask.new { |rdoc|
|
|
31
31
|
rdoc.title = "Action Web Service -- Web services for Action Pack"
|
32
32
|
rdoc.options << '--line-numbers --inline-source --main README --accessor class_inheritable_option=RW'
|
33
33
|
rdoc.rdoc_files.include('README')
|
34
|
+
rdoc.rdoc_files.include('CHANGELOG')
|
34
35
|
rdoc.rdoc_files.include('lib/action_web_service.rb')
|
35
36
|
rdoc.rdoc_files.include('lib/action_web_service/*.rb')
|
36
37
|
rdoc.rdoc_files.include('lib/action_web_service/api/*.rb')
|
37
38
|
rdoc.rdoc_files.include('lib/action_web_service/client/*.rb')
|
38
|
-
rdoc.rdoc_files.include('lib/action_web_service/
|
39
|
+
rdoc.rdoc_files.include('lib/action_web_service/container/*.rb')
|
39
40
|
rdoc.rdoc_files.include('lib/action_web_service/dispatcher/*.rb')
|
41
|
+
rdoc.rdoc_files.include('lib/action_web_service/protocol/*.rb')
|
40
42
|
rdoc.rdoc_files.include('lib/action_web_service/support/*.rb')
|
41
43
|
}
|
42
44
|
|
@@ -54,16 +56,16 @@ spec = Gem::Specification.new do |s|
|
|
54
56
|
s.rubyforge_project = "aws"
|
55
57
|
s.homepage = "http://www.rubyonrails.org"
|
56
58
|
|
57
|
-
s.add_dependency('actionpack', '
|
58
|
-
s.add_dependency('activerecord', '
|
59
|
-
s.add_dependency('activesupport', '
|
59
|
+
s.add_dependency('actionpack', '>= 1.5.1' + PKG_BUILD)
|
60
|
+
s.add_dependency('activerecord', '>= 1.8.0' + PKG_BUILD)
|
61
|
+
s.add_dependency('activesupport', '>= 1.0.1' + PKG_BUILD)
|
60
62
|
|
61
63
|
s.has_rdoc = true
|
62
64
|
s.requirements << 'none'
|
63
65
|
s.require_path = 'lib'
|
64
66
|
s.autorequire = 'action_web_service'
|
65
67
|
|
66
|
-
s.files = [ "Rakefile", "setup.rb", "README", "TODO", "
|
68
|
+
s.files = [ "Rakefile", "setup.rb", "README", "TODO", "CHANGELOG", "MIT-LICENSE" ]
|
67
69
|
s.files = s.files + Dir.glob( "examples/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
68
70
|
s.files = s.files + Dir.glob( "lib/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
69
71
|
s.files = s.files + Dir.glob( "test/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
@@ -85,7 +87,7 @@ end
|
|
85
87
|
# Publish documentation
|
86
88
|
desc "Publish the API documentation"
|
87
89
|
task :pdoc => [:rdoc] do
|
88
|
-
Rake::SshDirPublisher.new("davidhh@comox.textdrive.com", "public_html/
|
90
|
+
Rake::SshDirPublisher.new("davidhh@comox.textdrive.com", "public_html/aws", "doc").upload
|
89
91
|
end
|
90
92
|
|
91
93
|
|
@@ -94,7 +96,7 @@ def each_source_file(*args)
|
|
94
96
|
prefix ||= File.dirname(__FILE__)
|
95
97
|
open_file = true if open_file.nil?
|
96
98
|
includes ||= %w[lib\/action_web_service\.rb$ lib\/action_web_service\/.*\.rb$]
|
97
|
-
excludes ||= %w[]
|
99
|
+
excludes ||= %w[lib\/action_web_service\/vendor]
|
98
100
|
Find.find(prefix) do |file_name|
|
99
101
|
next if file_name =~ /\.svn/
|
100
102
|
file_name.gsub!(/^\.\//, '')
|
@@ -123,7 +125,7 @@ def each_source_file(*args)
|
|
123
125
|
end
|
124
126
|
end
|
125
127
|
|
126
|
-
desc "Count lines of the source code"
|
128
|
+
desc "Count lines of the AWS source code"
|
127
129
|
task :lines do
|
128
130
|
total_lines = total_loc = 0
|
129
131
|
puts "Per File:"
|
data/TODO
CHANGED
@@ -1,13 +1,12 @@
|
|
1
|
-
=
|
2
|
-
-
|
3
|
-
-
|
1
|
+
= 0.7.0
|
2
|
+
- WS Test Integration
|
3
|
+
- WS Scaffolding
|
4
|
+
- WS Generators
|
4
5
|
|
5
|
-
=
|
6
|
-
-
|
7
|
-
model classes) that doesn't require creation of a sanitized copy object with data
|
8
|
-
copied from the real one. Ideally this would let us get rid of
|
9
|
-
ActionWebService::Struct altogether and provide a block that would yield the
|
10
|
-
attributes and values. "Filters" ? Not sure how to integrate with SOAP though.
|
6
|
+
= 0.8.0
|
7
|
+
- Consumption of WSDL services
|
11
8
|
|
9
|
+
= Refactoring
|
10
|
+
- Port dispatcher tests to use test_invoke
|
12
11
|
- Don't have clean way to go from SOAP Class object to the xsd:NAME type
|
13
12
|
string -- NaHi possibly looking at remedying this situation
|
data/lib/action_web_service.rb
CHANGED
@@ -32,7 +32,10 @@ rescue LoadError
|
|
32
32
|
require_gem 'activerecord', '>= 1.6.0'
|
33
33
|
end
|
34
34
|
|
35
|
-
$:.unshift(File.dirname(__FILE__))
|
35
|
+
$:.unshift(File.dirname(__FILE__) + "/action_web_service/vendor/")
|
36
|
+
|
37
|
+
require 'action_web_service/support/class_inheritable_options'
|
38
|
+
require 'action_web_service/vendor/ws'
|
36
39
|
|
37
40
|
require 'action_web_service/base'
|
38
41
|
require 'action_web_service/client'
|
@@ -41,20 +44,21 @@ require 'action_web_service/api'
|
|
41
44
|
require 'action_web_service/struct'
|
42
45
|
require 'action_web_service/container'
|
43
46
|
require 'action_web_service/protocol'
|
47
|
+
require 'action_web_service/struct'
|
44
48
|
require 'action_web_service/dispatcher'
|
45
49
|
|
46
50
|
ActionWebService::Base.class_eval do
|
47
|
-
include ActionWebService::
|
51
|
+
include ActionWebService::Container::Direct
|
48
52
|
include ActionWebService::Invocation
|
49
53
|
end
|
50
54
|
|
51
55
|
ActionController::Base.class_eval do
|
52
|
-
include ActionWebService::
|
53
|
-
include ActionWebService::Protocol::Registry
|
56
|
+
include ActionWebService::Protocol::Discovery
|
54
57
|
include ActionWebService::Protocol::Soap
|
55
58
|
include ActionWebService::Protocol::XmlRpc
|
56
|
-
include ActionWebService::
|
57
|
-
include ActionWebService::
|
59
|
+
include ActionWebService::Container::Direct
|
60
|
+
include ActionWebService::Container::Delegated
|
61
|
+
include ActionWebService::Container::ActionController
|
58
62
|
include ActionWebService::Dispatcher
|
59
63
|
include ActionWebService::Dispatcher::ActionController
|
60
64
|
end
|
@@ -1,2 +1 @@
|
|
1
|
-
require 'action_web_service/api/
|
2
|
-
require 'action_web_service/api/action_controller'
|
1
|
+
require 'action_web_service/api/base'
|
@@ -1,70 +1,5 @@
|
|
1
1
|
module ActionWebService # :nodoc:
|
2
2
|
module API # :nodoc:
|
3
|
-
class APIError < ActionWebService::ActionWebServiceError # :nodoc:
|
4
|
-
end
|
5
|
-
|
6
|
-
def self.append_features(base) # :nodoc:
|
7
|
-
super
|
8
|
-
base.extend(ClassMethods)
|
9
|
-
end
|
10
|
-
|
11
|
-
module ClassMethods
|
12
|
-
# Attaches ActionWebService API +definition+ to the calling class.
|
13
|
-
#
|
14
|
-
# Action Controllers can have a default associated API, removing the need
|
15
|
-
# to call this method if you follow the Action Web Service naming conventions.
|
16
|
-
#
|
17
|
-
# A controller with a class name of GoogleSearchController will
|
18
|
-
# implicitly load <tt>app/apis/google_search_api.rb</tt>, and expect the
|
19
|
-
# API definition class to be named <tt>GoogleSearchAPI</tt> or
|
20
|
-
# <tt>GoogleSearchApi</tt>.
|
21
|
-
#
|
22
|
-
# ==== Service class example
|
23
|
-
#
|
24
|
-
# class MyService < ActionWebService::Base
|
25
|
-
# web_service_api MyAPI
|
26
|
-
# end
|
27
|
-
#
|
28
|
-
# class MyAPI < ActionWebService::API::Base
|
29
|
-
# ...
|
30
|
-
# end
|
31
|
-
#
|
32
|
-
# ==== Controller class example
|
33
|
-
#
|
34
|
-
# class MyController < ActionController::Base
|
35
|
-
# web_service_api MyAPI
|
36
|
-
# end
|
37
|
-
#
|
38
|
-
# class MyAPI < ActionWebService::API::Base
|
39
|
-
# ...
|
40
|
-
# end
|
41
|
-
def web_service_api(definition=nil)
|
42
|
-
if definition.nil?
|
43
|
-
read_inheritable_attribute("web_service_api")
|
44
|
-
else
|
45
|
-
if definition.is_a?(Symbol)
|
46
|
-
raise(APIError, "symbols can only be used for #web_service_api inside of a controller")
|
47
|
-
end
|
48
|
-
unless definition.respond_to?(:ancestors) && definition.ancestors.include?(Base)
|
49
|
-
raise(APIError, "#{definition.to_s} is not a valid API definition")
|
50
|
-
end
|
51
|
-
write_inheritable_attribute("web_service_api", definition)
|
52
|
-
call_web_service_api_callbacks(self, definition)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def add_web_service_api_callback(&block) # :nodoc:
|
57
|
-
write_inheritable_array("web_service_api_callbacks", [block])
|
58
|
-
end
|
59
|
-
|
60
|
-
private
|
61
|
-
def call_web_service_api_callbacks(container_class, definition)
|
62
|
-
(read_inheritable_attribute("web_service_api_callbacks") || []).each do |block|
|
63
|
-
block.call(container_class, definition)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
3
|
# A web service API class specifies the methods that will be available for
|
69
4
|
# invocation for an API. It also contains metadata such as the method type
|
70
5
|
# signature hints.
|
@@ -78,6 +13,12 @@ module ActionWebService # :nodoc:
|
|
78
13
|
# Whether to transform the public API method names into camel-cased names
|
79
14
|
class_inheritable_option :inflect_names, true
|
80
15
|
|
16
|
+
# Whether to allow ActiveRecord::Base models in <tt>:expects</tt>.
|
17
|
+
# The default is +false+, you should be aware of the security implications
|
18
|
+
# of allowing this, and ensure that you don't allow remote callers to
|
19
|
+
# easily overwrite data they should not have access to.
|
20
|
+
class_inheritable_option :allow_active_record_expects, false
|
21
|
+
|
81
22
|
# If present, the name of a method to call when the remote caller
|
82
23
|
# tried to call a nonexistent method. Semantically equivalent to
|
83
24
|
# +method_missing+.
|
@@ -87,8 +28,6 @@ module ActionWebService # :nodoc:
|
|
87
28
|
private_class_method :new, :allocate
|
88
29
|
|
89
30
|
class << self
|
90
|
-
include ActionWebService::Signature
|
91
|
-
|
92
31
|
# API methods have a +name+, which must be the Ruby method name to use when
|
93
32
|
# performing the invocation on the web service object.
|
94
33
|
#
|
@@ -125,13 +64,13 @@ module ActionWebService # :nodoc:
|
|
125
64
|
expects = options[:expects]
|
126
65
|
returns = options[:returns]
|
127
66
|
end
|
128
|
-
expects = canonical_signature(expects)
|
129
|
-
returns = canonical_signature(returns)
|
67
|
+
expects = canonical_signature(expects)
|
68
|
+
returns = canonical_signature(returns)
|
130
69
|
if expects
|
131
70
|
expects.each do |param|
|
132
|
-
klass =
|
71
|
+
klass = WS::BaseTypes.canonical_param_type_class(param)
|
133
72
|
klass = klass[0] if klass.is_a?(Array)
|
134
|
-
if klass.ancestors.include?(ActiveRecord::Base)
|
73
|
+
if klass.ancestors.include?(ActiveRecord::Base) && !allow_active_record_expects
|
135
74
|
raise(ActionWebServiceError, "ActiveRecord model classes not allowed in :expects")
|
136
75
|
end
|
137
76
|
end
|
@@ -186,6 +125,10 @@ module ActionWebService # :nodoc:
|
|
186
125
|
end
|
187
126
|
end
|
188
127
|
|
128
|
+
def canonical_signature(signature)
|
129
|
+
return nil if signature.nil?
|
130
|
+
signature.map{|spec| WS::BaseTypes.canonical_param_type_spec(spec)}
|
131
|
+
end
|
189
132
|
end
|
190
133
|
end
|
191
134
|
end
|
@@ -12,28 +12,17 @@ module ActionWebService # :nodoc:
|
|
12
12
|
def method_missing(name, *args) # :nodoc:
|
13
13
|
call_name = method_name(name)
|
14
14
|
return super(name, *args) if call_name.nil?
|
15
|
-
perform_invocation(call_name, args)
|
15
|
+
self.perform_invocation(call_name, args)
|
16
16
|
end
|
17
17
|
|
18
|
-
protected
|
19
|
-
def perform_invocation(method_name, args) # :nodoc:
|
20
|
-
raise NotImplementedError, "use a protocol-specific client"
|
21
|
-
end
|
22
|
-
|
23
18
|
private
|
24
19
|
def method_name(name)
|
25
20
|
if @api.has_api_method?(name.to_sym)
|
26
21
|
name.to_s
|
27
22
|
elsif @api.has_public_api_method?(name.to_s)
|
28
23
|
@api.api_method_name(name.to_s).to_s
|
29
|
-
else
|
30
|
-
nil
|
31
24
|
end
|
32
25
|
end
|
33
|
-
|
34
|
-
def lookup_class(klass)
|
35
|
-
klass.is_a?(Hash) ? klass.values[0] : klass
|
36
|
-
end
|
37
26
|
end
|
38
27
|
end
|
39
28
|
end
|
@@ -24,17 +24,36 @@ module ActionWebService # :nodoc:
|
|
24
24
|
# will be sent with HTTP POST.
|
25
25
|
#
|
26
26
|
# Valid options:
|
27
|
-
# [<tt>:
|
28
|
-
#
|
27
|
+
# [<tt>:type_namespace</tt>] If the remote server has used a custom namespace to
|
28
|
+
# declare its custom types, you can specify it here
|
29
|
+
# [<tt>:method_namespace</tt>] If the remote server has used a custom namespace to
|
30
|
+
# declare its methods, you can specify it here
|
31
|
+
# [<tt>:driver_options</tt>] If you want to supply any custom SOAP RPC driver
|
32
|
+
# options, you can provide them as a Hash here
|
33
|
+
#
|
34
|
+
# The <tt>:driver_options</tt> option can be used to configure the backend SOAP
|
35
|
+
# RPC driver. An example of configuring the SOAP backend to do
|
36
|
+
# client-certificate authenticated SSL connections to the server:
|
37
|
+
#
|
38
|
+
# opts = {}
|
39
|
+
# opts['protocol.http.ssl_config.verify_mode'] = 'OpenSSL::SSL::VERIFY_PEER'
|
40
|
+
# opts['protocol.http.ssl_config.client_cert'] = client_cert_file_path
|
41
|
+
# opts['protocol.http.ssl_config.client_key'] = client_key_file_path
|
42
|
+
# opts['protocol.http.ssl_config.ca_file'] = ca_cert_file_path
|
43
|
+
# client = ActionWebService::Client::Soap.new(api, 'https://some/service', :driver_options => opts)
|
29
44
|
def initialize(api, endpoint_uri, options={})
|
30
45
|
super(api, endpoint_uri)
|
31
|
-
@
|
32
|
-
@
|
33
|
-
@
|
34
|
-
@
|
46
|
+
@type_namespace = options[:type_namespace] || 'urn:ActionWebService'
|
47
|
+
@method_namespace = options[:method_namespace] || 'urn:ActionWebService'
|
48
|
+
@driver_options = options[:driver_options] || {}
|
49
|
+
@marshaler = WS::Marshaling::SoapMarshaler.new @type_namespace
|
50
|
+
@encoder = WS::Encoding::SoapRpcEncoding.new @method_namespace
|
35
51
|
@soap_action_base = options[:soap_action_base]
|
36
52
|
@soap_action_base ||= URI.parse(endpoint_uri).path
|
37
53
|
@driver = create_soap_rpc_driver(api, endpoint_uri)
|
54
|
+
@driver_options.each do |name, value|
|
55
|
+
@driver.options[name.to_s] = value.to_s
|
56
|
+
end
|
38
57
|
end
|
39
58
|
|
40
59
|
protected
|
@@ -48,35 +67,48 @@ module ActionWebService # :nodoc:
|
|
48
67
|
|
49
68
|
private
|
50
69
|
def create_soap_rpc_driver(api, endpoint_uri)
|
51
|
-
@
|
70
|
+
register_api(@marshaler, api)
|
52
71
|
driver = SoapDriver.new(endpoint_uri, nil)
|
53
|
-
driver.mapping_registry = @
|
72
|
+
driver.mapping_registry = @marshaler.registry
|
54
73
|
api.api_methods.each do |name, info|
|
55
74
|
public_name = api.public_api_method_name(name)
|
56
|
-
qname = XSD::QName.new(@
|
75
|
+
qname = XSD::QName.new(@method_namespace, public_name)
|
57
76
|
action = soap_action(public_name)
|
58
77
|
expects = info[:expects]
|
59
78
|
returns = info[:returns]
|
60
79
|
param_def = []
|
61
|
-
i =
|
80
|
+
i = 0
|
62
81
|
if expects
|
63
|
-
expects.each do |
|
64
|
-
param_name =
|
65
|
-
|
66
|
-
|
67
|
-
param_def << ['in', param_name, mapping.registry_mapping]
|
82
|
+
expects.each do |spec|
|
83
|
+
param_name = spec.is_a?(Hash) ? spec.keys[0].to_s : "param#{i}"
|
84
|
+
type_binding = @marshaler.register_type(spec)
|
85
|
+
param_def << ['in', param_name, type_binding.mapping]
|
68
86
|
i += 1
|
69
87
|
end
|
70
88
|
end
|
71
89
|
if returns
|
72
|
-
|
73
|
-
param_def << ['retval', 'return', mapping
|
90
|
+
type_binding = @marshaler.register_type(returns[0])
|
91
|
+
param_def << ['retval', 'return', type_binding.mapping]
|
74
92
|
end
|
75
93
|
driver.add_method(qname, action, name.to_s, param_def)
|
76
94
|
end
|
77
95
|
driver
|
78
96
|
end
|
79
97
|
|
98
|
+
def register_api(marshaler, api)
|
99
|
+
type_bindings = []
|
100
|
+
api.api_methods.each do |name, info|
|
101
|
+
expects, returns = info[:expects], info[:returns]
|
102
|
+
if expects
|
103
|
+
expects.each{|type| type_bindings << marshaler.register_type(type)}
|
104
|
+
end
|
105
|
+
if returns
|
106
|
+
returns.each{|type| type_bindings << marshaler.register_type(type)}
|
107
|
+
end
|
108
|
+
end
|
109
|
+
type_bindings
|
110
|
+
end
|
111
|
+
|
80
112
|
class SoapDriver < SOAP::RPC::Driver # :nodoc:
|
81
113
|
def add_method(qname, soapaction, name, param_def)
|
82
114
|
@proxy.add_rpc_method(qname, soapaction, name, param_def)
|