actionwebservice 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|