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
@@ -1,55 +0,0 @@
|
|
1
|
-
module ActionWebService # :nodoc:
|
2
|
-
module Protocol # :nodoc:
|
3
|
-
HeaderAndBody = :header_and_body
|
4
|
-
BodyOnly = :body_only
|
5
|
-
|
6
|
-
module Registry # :nodoc:
|
7
|
-
def self.append_features(base) # :nodoc:
|
8
|
-
super
|
9
|
-
base.extend(ClassMethods)
|
10
|
-
base.send(:include, ActionWebService::Protocol::Registry::InstanceMethods)
|
11
|
-
end
|
12
|
-
|
13
|
-
module ClassMethods # :nodoc:
|
14
|
-
def register_protocol(type, klass) # :nodoc:
|
15
|
-
case type
|
16
|
-
when HeaderAndBody
|
17
|
-
write_inheritable_array("header_and_body_protocols", [klass])
|
18
|
-
when BodyOnly
|
19
|
-
write_inheritable_array("body_only_protocols", [klass])
|
20
|
-
else
|
21
|
-
raise(ProtocolError, "unknown protocol type #{type}")
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
module InstanceMethods # :nodoc:
|
27
|
-
private
|
28
|
-
def probe_request_protocol(action_pack_request)
|
29
|
-
(header_and_body_protocols + body_only_protocols).each do |protocol|
|
30
|
-
protocol_request = protocol.create_protocol_request(self.class, action_pack_request)
|
31
|
-
return protocol_request if protocol_request
|
32
|
-
end
|
33
|
-
raise(ProtocolError, "unsupported request message format")
|
34
|
-
end
|
35
|
-
|
36
|
-
def probe_protocol_client(api, protocol_name, endpoint_uri, options)
|
37
|
-
(header_and_body_protocols + body_only_protocols).each do |protocol|
|
38
|
-
protocol_client = protocol.create_protocol_client(api, protocol_name, endpoint_uri, options)
|
39
|
-
return protocol_client if protocol_client
|
40
|
-
end
|
41
|
-
raise(ProtocolError, "unsupported client protocol :#{protocol_name}")
|
42
|
-
end
|
43
|
-
|
44
|
-
def header_and_body_protocols
|
45
|
-
self.class.read_inheritable_attribute("header_and_body_protocols") || []
|
46
|
-
end
|
47
|
-
|
48
|
-
def body_only_protocols
|
49
|
-
self.class.read_inheritable_attribute("body_only_protocols") || []
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
@@ -1,100 +0,0 @@
|
|
1
|
-
module ActionWebService # :nodoc:
|
2
|
-
# Action Web Service parameter specifiers may contain symbols or strings
|
3
|
-
# instead of Class objects, for a limited set of base types.
|
4
|
-
#
|
5
|
-
# This provides an unambiguous way to specify that a given parameter
|
6
|
-
# contains an integer or boolean value, for example.
|
7
|
-
#
|
8
|
-
# The allowed set of symbol/string aliases:
|
9
|
-
#
|
10
|
-
# [<tt>:int</tt>] any integer value
|
11
|
-
# [<tt>:float</tt>] any floating point value
|
12
|
-
# [<tt>:string</tt>] any string value
|
13
|
-
# [<tt>:bool</tt>] any boolean value
|
14
|
-
# [<tt>:time</tt>] any value containing both date and time
|
15
|
-
# [<tt>:date</tt>] any value containing only a date
|
16
|
-
module Signature
|
17
|
-
class SignatureError < StandardError # :nodoc:
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
def canonical_signature(params)
|
22
|
-
return nil if params.nil?
|
23
|
-
params.map do |param|
|
24
|
-
klass = signature_parameter_class(param)
|
25
|
-
if param.is_a?(Hash)
|
26
|
-
param[param.keys[0]] = klass
|
27
|
-
param
|
28
|
-
else
|
29
|
-
klass
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def signature_parameter_class(param)
|
35
|
-
param = param.is_a?(Hash) ? param.values[0] : param
|
36
|
-
is_array = param.is_a?(Array)
|
37
|
-
param = is_array ? param[0] : param
|
38
|
-
param = param.is_a?(String) ? param.to_sym : param
|
39
|
-
param = param.is_a?(Symbol) ? signature_ruby_class(param) : param
|
40
|
-
is_array ? [param] : param
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
|
-
def canonical_signature_base_type(base_type)
|
45
|
-
base_type = base_type.to_sym
|
46
|
-
case base_type
|
47
|
-
when :int, :integer, :fixnum, :bignum
|
48
|
-
:int
|
49
|
-
when :string, :base64
|
50
|
-
:string
|
51
|
-
when :bool, :boolean
|
52
|
-
:bool
|
53
|
-
when :float, :double
|
54
|
-
:float
|
55
|
-
when :time, :datetime, :timestamp
|
56
|
-
:time
|
57
|
-
when :date
|
58
|
-
:date
|
59
|
-
else
|
60
|
-
raise(SignatureError, ":#{base_type} is not an ActionWebService base type")
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def signature_ruby_class(base_type)
|
65
|
-
case canonical_signature_base_type(base_type)
|
66
|
-
when :int
|
67
|
-
Integer
|
68
|
-
when :string
|
69
|
-
String
|
70
|
-
when :bool
|
71
|
-
TrueClass
|
72
|
-
when :float
|
73
|
-
Float
|
74
|
-
when :time
|
75
|
-
Time
|
76
|
-
when :date
|
77
|
-
Date
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def signature_base_type(ruby_class)
|
82
|
-
case ruby_class
|
83
|
-
when Bignum, Integer, Fixnum
|
84
|
-
:int
|
85
|
-
when String
|
86
|
-
:string
|
87
|
-
when TrueClass, FalseClass
|
88
|
-
:bool
|
89
|
-
when Float, Numeric, Precision
|
90
|
-
:float
|
91
|
-
when Time, DateTime
|
92
|
-
:time
|
93
|
-
when Date
|
94
|
-
:date
|
95
|
-
else
|
96
|
-
raise(SignatureError, "#{ruby_class.name} is not an ActionWebService base type")
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
data/test/abstract_soap.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/abstract_unit'
|
2
|
-
require 'soap/rpc/element'
|
3
|
-
|
4
|
-
class SoapTestError < StandardError
|
5
|
-
end
|
6
|
-
|
7
|
-
class AbstractSoapTest < Test::Unit::TestCase
|
8
|
-
def default_test
|
9
|
-
end
|
10
|
-
|
11
|
-
protected
|
12
|
-
def service_name
|
13
|
-
raise NotImplementedError
|
14
|
-
end
|
15
|
-
|
16
|
-
def do_soap_call(public_method_name, *args)
|
17
|
-
mapper = @container.class.soap_mapper
|
18
|
-
param_def = []
|
19
|
-
i = 1
|
20
|
-
args.each do |arg|
|
21
|
-
mapping = mapper.lookup(arg.class)
|
22
|
-
param_def << ["in", "param#{i}", mapping.registry_mapping]
|
23
|
-
i += 1
|
24
|
-
end
|
25
|
-
qname = XSD::QName.new('urn:ActionWebService', public_method_name)
|
26
|
-
request = SOAP::RPC::SOAPMethodRequest.new(qname, param_def)
|
27
|
-
soap_args = []
|
28
|
-
i = 1
|
29
|
-
args.each do |arg|
|
30
|
-
soap_args << ["param#{i}", SOAP::Mapping.obj2soap(arg)]
|
31
|
-
i += 1
|
32
|
-
end
|
33
|
-
request.set_param(soap_args)
|
34
|
-
header = SOAP::SOAPHeader.new
|
35
|
-
body = SOAP::SOAPBody.new(request)
|
36
|
-
envelope = SOAP::SOAPEnvelope.new(header, body)
|
37
|
-
raw_request = SOAP::Processor.marshal(envelope)
|
38
|
-
test_request = ActionController::TestRequest.new
|
39
|
-
test_request.request_parameters['action'] = service_name
|
40
|
-
test_request.env['REQUEST_METHOD'] = "POST"
|
41
|
-
test_request.env['HTTP_CONTENTTYPE'] = 'text/xml'
|
42
|
-
test_request.env['HTTP_SOAPACTION'] = "/soap/#{service_name}/#{public_method_name}"
|
43
|
-
test_request.env['RAW_POST_DATA'] = raw_request
|
44
|
-
test_response = ActionController::TestResponse.new
|
45
|
-
response = yield test_request, test_response
|
46
|
-
raw_body = response.respond_to?(:body) ? response.body : response.raw_body
|
47
|
-
envelope = SOAP::Processor.unmarshal(raw_body)
|
48
|
-
if envelope
|
49
|
-
if envelope.body.response
|
50
|
-
SOAP::Mapping.soap2obj(envelope.body.response)
|
51
|
-
else
|
52
|
-
nil
|
53
|
-
end
|
54
|
-
else
|
55
|
-
raise(SoapTestError, "empty/invalid body from server")
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
@@ -1,186 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/abstract_soap'
|
2
|
-
require 'wsdl/parser'
|
3
|
-
|
4
|
-
module DispatcherActionControllerTest
|
5
|
-
class API < ActionWebService::API::Base
|
6
|
-
api_method :add, :expects => [:int, :int], :returns => [:int]
|
7
|
-
end
|
8
|
-
|
9
|
-
class DirectAPI < ActionWebService::API::Base
|
10
|
-
api_method :add, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int]
|
11
|
-
api_method :before_filtered
|
12
|
-
api_method :after_filtered, :returns => [:int]
|
13
|
-
api_method :thrower
|
14
|
-
end
|
15
|
-
|
16
|
-
class Service < ActionWebService::Base
|
17
|
-
web_service_api API
|
18
|
-
|
19
|
-
attr :added
|
20
|
-
|
21
|
-
def add(a, b)
|
22
|
-
@added = a + b
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class AbstractController < ActionController::Base
|
27
|
-
def generate_wsdl(container, uri, soap_action_base)
|
28
|
-
to_wsdl(container, uri, soap_action_base)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
class DelegatedController < AbstractController
|
33
|
-
web_service_dispatching_mode :delegated
|
34
|
-
|
35
|
-
web_service(:test_service) { @service ||= Service.new; @service }
|
36
|
-
end
|
37
|
-
|
38
|
-
class DirectController < AbstractController
|
39
|
-
web_service_api DirectAPI
|
40
|
-
web_service_dispatching_mode :direct
|
41
|
-
|
42
|
-
before_filter :alwaysfail, :only => [:before_filtered]
|
43
|
-
after_filter :alwaysok, :only => [:after_filtered]
|
44
|
-
|
45
|
-
attr :added
|
46
|
-
attr :before_filter_called
|
47
|
-
attr :before_filter_target_called
|
48
|
-
attr :after_filter_called
|
49
|
-
attr :after_filter_target_called
|
50
|
-
|
51
|
-
def initialize
|
52
|
-
@before_filter_called = false
|
53
|
-
@before_filter_target_called = false
|
54
|
-
@after_filter_called = false
|
55
|
-
@after_filter_target_called = false
|
56
|
-
end
|
57
|
-
|
58
|
-
def add
|
59
|
-
@added = @params['a'] + @params['b']
|
60
|
-
end
|
61
|
-
|
62
|
-
def before_filtered
|
63
|
-
@before_filter_target_called = true
|
64
|
-
end
|
65
|
-
|
66
|
-
def after_filtered
|
67
|
-
@after_filter_target_called = true
|
68
|
-
5
|
69
|
-
end
|
70
|
-
|
71
|
-
def thrower
|
72
|
-
raise "Hi, I'm a SOAP exception"
|
73
|
-
end
|
74
|
-
|
75
|
-
protected
|
76
|
-
def alwaysfail
|
77
|
-
@before_filter_called = true
|
78
|
-
false
|
79
|
-
end
|
80
|
-
|
81
|
-
def alwaysok
|
82
|
-
@after_filter_called = true
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
class TC_DispatcherActionController < AbstractSoapTest
|
88
|
-
include DispatcherActionControllerTest
|
89
|
-
|
90
|
-
def test_direct_dispatching
|
91
|
-
@container = DirectController.new
|
92
|
-
assert(do_soap_call('Add', 20, 50) == 70)
|
93
|
-
assert(@container.added == 70)
|
94
|
-
end
|
95
|
-
|
96
|
-
def test_direct_entrypoint
|
97
|
-
@container = DirectController.new
|
98
|
-
assert(@container.respond_to?(:api))
|
99
|
-
end
|
100
|
-
|
101
|
-
def test_direct_filtering
|
102
|
-
@container = DirectController.new
|
103
|
-
assert(@container.before_filter_called == false)
|
104
|
-
assert(@container.before_filter_target_called == false)
|
105
|
-
assert(do_soap_call('BeforeFiltered').nil?)
|
106
|
-
assert(@container.before_filter_called == true)
|
107
|
-
assert(@container.before_filter_target_called == false)
|
108
|
-
assert(@container.after_filter_called == false)
|
109
|
-
assert(@container.after_filter_target_called == false)
|
110
|
-
assert(do_soap_call('AfterFiltered') == 5)
|
111
|
-
assert(@container.after_filter_called == true)
|
112
|
-
assert(@container.after_filter_target_called == true)
|
113
|
-
end
|
114
|
-
|
115
|
-
def test_delegated_dispatching
|
116
|
-
@container = DelegatedController.new
|
117
|
-
assert(do_soap_call('Add', 50, 80) == 130)
|
118
|
-
assert(service.added == 130)
|
119
|
-
end
|
120
|
-
|
121
|
-
def test_exception_marshaling
|
122
|
-
@container = DirectController.new
|
123
|
-
result = do_soap_call('Thrower')
|
124
|
-
exception = result.detail
|
125
|
-
assert(exception.cause.is_a?(RuntimeError))
|
126
|
-
assert_equal("Hi, I'm a SOAP exception", exception.cause.message)
|
127
|
-
@container.web_service_exception_reporting = false
|
128
|
-
assert_raises(SoapTestError) do
|
129
|
-
do_soap_call('Thrower')
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
def test_wsdl_generation
|
134
|
-
ensure_valid_wsdl_generation DelegatedController.new
|
135
|
-
ensure_valid_wsdl_generation DirectController.new
|
136
|
-
end
|
137
|
-
|
138
|
-
def
|
139
|
-
|
140
|
-
def test_wsdl_action
|
141
|
-
ensure_valid_wsdl_action DelegatedController.new
|
142
|
-
ensure_valid_wsdl_action DirectController.new
|
143
|
-
end
|
144
|
-
|
145
|
-
protected
|
146
|
-
def service_name
|
147
|
-
@container.is_a?(DelegatedController) ? 'test_service' : 'api'
|
148
|
-
end
|
149
|
-
|
150
|
-
def service
|
151
|
-
@container.web_service_object(:test_service)
|
152
|
-
end
|
153
|
-
|
154
|
-
def do_soap_call(public_method_name, *args)
|
155
|
-
super(public_method_name, *args) do |test_request, test_response|
|
156
|
-
response = @container.process(test_request, test_response)
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
def ensure_valid_wsdl_generation(controller)
|
161
|
-
wsdl = controller.generate_wsdl(controller, 'http://localhost:3000/test/', '/test')
|
162
|
-
ensure_valid_wsdl(wsdl)
|
163
|
-
end
|
164
|
-
|
165
|
-
def ensure_valid_wsdl(wsdl)
|
166
|
-
definitions = WSDL::Parser.new.parse(wsdl)
|
167
|
-
assert(definitions.is_a?(WSDL::Definitions))
|
168
|
-
definitions.bindings.each do |binding|
|
169
|
-
assert(binding.name.name.index(':').nil?)
|
170
|
-
end
|
171
|
-
definitions.services.each do |service|
|
172
|
-
service.ports.each do |port|
|
173
|
-
assert(port.name.name.index(':').nil?)
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
def ensure_valid_wsdl_action(controller)
|
179
|
-
test_request = ActionController::TestRequest.new({ 'action' => 'wsdl' })
|
180
|
-
test_request.env['REQUEST_METHOD'] = 'GET'
|
181
|
-
test_request.env['HTTP_HOST'] = 'localhost:3000'
|
182
|
-
test_response = ActionController::TestResponse.new
|
183
|
-
wsdl = controller.process(test_request, test_response).body
|
184
|
-
ensure_valid_wsdl(wsdl)
|
185
|
-
end
|
186
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/abstract_unit'
|
2
|
-
|
3
|
-
|
4
|
-
module Foo
|
5
|
-
include ActionWebService::Protocol
|
6
|
-
|
7
|
-
def self.append_features(base)
|
8
|
-
super
|
9
|
-
base.register_protocol(BodyOnly, FooMinimalProtocol)
|
10
|
-
base.register_protocol(HeaderAndBody, FooMinimalProtocolTwo)
|
11
|
-
base.register_protocol(HeaderAndBody, FooMinimalProtocolTwo)
|
12
|
-
base.register_protocol(HeaderAndBody, FooFullProtocol)
|
13
|
-
end
|
14
|
-
|
15
|
-
class FooFullProtocol < AbstractProtocol
|
16
|
-
def self.create_protocol_request(klass, request)
|
17
|
-
protocol = FooFullProtocol.new klass
|
18
|
-
ActionWebService::Protocol::ProtocolRequest.new(protocol, '', '', '', '')
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
class FooMinimalProtocol < AbstractProtocol
|
23
|
-
def self.create_protocol_request(klass, request)
|
24
|
-
protocol = FooMinimalProtocol.new klass
|
25
|
-
ActionWebService::Protocol::ProtocolRequest.new(protocol, '', '', '', '')
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
class FooMinimalProtocolTwo < AbstractProtocol
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
class ProtocolRegistry
|
34
|
-
include ActionWebService::Protocol::Registry
|
35
|
-
include Foo
|
36
|
-
|
37
|
-
def all_protocols
|
38
|
-
header_and_body_protocols + body_only_protocols
|
39
|
-
end
|
40
|
-
|
41
|
-
def protocol_request
|
42
|
-
probe_request_protocol(nil)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
class TC_ProtocolRegistry < Test::Unit::TestCase
|
48
|
-
def test_registration
|
49
|
-
registry = ProtocolRegistry.new
|
50
|
-
assert(registry.all_protocols.length == 4)
|
51
|
-
assert(registry.protocol_request.protocol.is_a?(Foo::FooFullProtocol))
|
52
|
-
end
|
53
|
-
end
|