axtro-actionwebservice 2.3.5.1.20101118142125
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 +335 -0
- data/MIT-LICENSE +21 -0
- data/README +381 -0
- data/Rakefile +184 -0
- data/TODO +32 -0
- data/examples/googlesearch/README +143 -0
- data/examples/googlesearch/autoloading/google_search_api.rb +51 -0
- data/examples/googlesearch/autoloading/google_search_controller.rb +58 -0
- data/examples/googlesearch/delegated/google_search_service.rb +109 -0
- data/examples/googlesearch/delegated/search_controller.rb +8 -0
- data/examples/googlesearch/direct/google_search_api.rb +51 -0
- data/examples/googlesearch/direct/search_controller.rb +59 -0
- data/examples/metaWeblog/README +17 -0
- data/examples/metaWeblog/apis/blogger_api.rb +61 -0
- data/examples/metaWeblog/apis/blogger_service.rb +35 -0
- data/examples/metaWeblog/apis/meta_weblog_api.rb +68 -0
- data/examples/metaWeblog/apis/meta_weblog_service.rb +49 -0
- data/examples/metaWeblog/controllers/xmlrpc_controller.rb +17 -0
- data/generators/web_service/USAGE +28 -0
- data/generators/web_service/templates/api_definition.rb +6 -0
- data/generators/web_service/templates/controller.rb +9 -0
- data/generators/web_service/templates/functional_test.rb +20 -0
- data/generators/web_service/web_service_generator.rb +30 -0
- data/lib/action_web_service.rb +61 -0
- data/lib/action_web_service/acts_as_web_service.rb +26 -0
- data/lib/action_web_service/api.rb +298 -0
- data/lib/action_web_service/base.rb +39 -0
- data/lib/action_web_service/casting.rb +160 -0
- data/lib/action_web_service/client.rb +4 -0
- data/lib/action_web_service/client/base.rb +29 -0
- data/lib/action_web_service/client/soap_client.rb +114 -0
- data/lib/action_web_service/client/xmlrpc_client.rb +59 -0
- data/lib/action_web_service/container.rb +4 -0
- data/lib/action_web_service/container/action_controller_container.rb +94 -0
- 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.rb +3 -0
- data/lib/action_web_service/dispatcher/abstract.rb +209 -0
- data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +397 -0
- data/lib/action_web_service/invocation.rb +203 -0
- data/lib/action_web_service/protocol.rb +5 -0
- data/lib/action_web_service/protocol/abstract.rb +113 -0
- data/lib/action_web_service/protocol/discovery.rb +38 -0
- data/lib/action_web_service/protocol/soap_protocol.rb +177 -0
- data/lib/action_web_service/protocol/soap_protocol/marshaler.rb +243 -0
- data/lib/action_web_service/protocol/soap_protocol/marshaler.rb~ +243 -0
- data/lib/action_web_service/protocol/xmlrpc_protocol.rb +124 -0
- data/lib/action_web_service/scaffolding.rb +282 -0
- data/lib/action_web_service/simple.rb +54 -0
- data/lib/action_web_service/string_to_datetime_for_soap.rb +17 -0
- data/lib/action_web_service/struct.rb +69 -0
- data/lib/action_web_service/support/class_inheritable_options.rb +27 -0
- data/lib/action_web_service/support/signature_types.rb +262 -0
- data/lib/action_web_service/templates/scaffolds/layout.html.erb +65 -0
- data/lib/action_web_service/templates/scaffolds/methods.html.erb +6 -0
- data/lib/action_web_service/templates/scaffolds/parameters.html.erb +29 -0
- data/lib/action_web_service/templates/scaffolds/result.html.erb +30 -0
- data/lib/action_web_service/test_invoke.rb +111 -0
- data/lib/action_web_service/version.rb +11 -0
- data/lib/action_web_service/version.rb~ +10 -0
- data/lib/actionwebservice.rb +2 -0
- data/setup.rb +1380 -0
- data/test/abstract_client.rb +185 -0
- data/test/abstract_dispatcher.rb +550 -0
- data/test/abstract_unit.rb +44 -0
- data/test/api_test.rb +103 -0
- data/test/apis/auto_load_api.rb +4 -0
- data/test/apis/broken_auto_load_api.rb +3 -0
- data/test/base_test.rb +43 -0
- data/test/casting_test.rb +96 -0
- data/test/client_soap_test.rb +157 -0
- data/test/client_xmlrpc_test.rb +155 -0
- data/test/container_test.rb +76 -0
- data/test/dispatcher_action_controller_soap_test.rb +147 -0
- data/test/dispatcher_action_controller_xmlrpc_test.rb +60 -0
- data/test/fixtures/db_definitions/mysql.sql +8 -0
- data/test/fixtures/db_definitions/sqlite3.sql +8 -0
- data/test/fixtures/users.yml +12 -0
- data/test/gencov +3 -0
- data/test/invocation_test.rb +187 -0
- data/test/run +6 -0
- data/test/scaffolded_controller_test.rb +148 -0
- data/test/struct_test.rb +85 -0
- data/test/test_invoke_test.rb +114 -0
- metadata +167 -0
@@ -0,0 +1,185 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'abstract_unit'
|
3
|
+
require 'webrick'
|
4
|
+
require 'webrick/log'
|
5
|
+
require 'singleton'
|
6
|
+
|
7
|
+
module ClientTest
|
8
|
+
class Person < ActionWebService::Struct
|
9
|
+
member :firstnames, [:string]
|
10
|
+
member :lastname, :string
|
11
|
+
|
12
|
+
def ==(other)
|
13
|
+
firstnames == other.firstnames && lastname == other.lastname
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Inner < ActionWebService::Struct
|
18
|
+
member :name, :string
|
19
|
+
end
|
20
|
+
|
21
|
+
class Outer < ActionWebService::Struct
|
22
|
+
member :name, :string
|
23
|
+
member :inner, Inner
|
24
|
+
end
|
25
|
+
|
26
|
+
class User < ActiveRecord::Base
|
27
|
+
end
|
28
|
+
|
29
|
+
module Accounting
|
30
|
+
class User < ActiveRecord::Base
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class WithModel < ActionWebService::Struct
|
35
|
+
member :user, User
|
36
|
+
member :users, [User]
|
37
|
+
end
|
38
|
+
|
39
|
+
class WithMultiDimArray < ActionWebService::Struct
|
40
|
+
member :pref, [[:string]]
|
41
|
+
end
|
42
|
+
|
43
|
+
class API < ActionWebService::API::Base
|
44
|
+
api_method :void
|
45
|
+
api_method :normal, :expects => [:int, :int], :returns => [:int]
|
46
|
+
api_method :array_return, :returns => [[Person]]
|
47
|
+
api_method :struct_pass, :expects => [[Person]], :returns => [:bool]
|
48
|
+
api_method :nil_struct_return, :returns => [Person]
|
49
|
+
api_method :inner_nil, :returns => [Outer]
|
50
|
+
api_method :client_container, :returns => [:int]
|
51
|
+
api_method :named_parameters, :expects => [{:key=>:string}, {:id=>:int}]
|
52
|
+
api_method :thrower
|
53
|
+
api_method :user_return, :returns => [User]
|
54
|
+
api_method :with_model_return, :returns => [WithModel]
|
55
|
+
api_method :scoped_model_return, :returns => [Accounting::User]
|
56
|
+
api_method :multi_dim_return, :returns => [WithMultiDimArray]
|
57
|
+
end
|
58
|
+
|
59
|
+
class NullLogOut
|
60
|
+
def <<(*args); end
|
61
|
+
end
|
62
|
+
|
63
|
+
class Container < ActionController::Base
|
64
|
+
acts_as_web_service
|
65
|
+
web_service_api API
|
66
|
+
|
67
|
+
attr_accessor :value_void
|
68
|
+
attr_accessor :value_normal
|
69
|
+
attr_accessor :value_array_return
|
70
|
+
attr_accessor :value_struct_pass
|
71
|
+
attr_accessor :value_named_parameters
|
72
|
+
|
73
|
+
def initialize
|
74
|
+
@value_void = nil
|
75
|
+
@value_normal = nil
|
76
|
+
@value_array_return = nil
|
77
|
+
@value_struct_pass = nil
|
78
|
+
@value_named_parameters = nil
|
79
|
+
end
|
80
|
+
|
81
|
+
def void
|
82
|
+
@value_void = @method_params
|
83
|
+
end
|
84
|
+
|
85
|
+
def normal
|
86
|
+
@value_normal = @method_params
|
87
|
+
5
|
88
|
+
end
|
89
|
+
|
90
|
+
def array_return
|
91
|
+
person = Person.new
|
92
|
+
person.firstnames = ["one", "two"]
|
93
|
+
person.lastname = "last"
|
94
|
+
@value_array_return = [person]
|
95
|
+
end
|
96
|
+
|
97
|
+
def struct_pass
|
98
|
+
@value_struct_pass = @method_params
|
99
|
+
true
|
100
|
+
end
|
101
|
+
|
102
|
+
def nil_struct_return
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
|
106
|
+
def inner_nil
|
107
|
+
Outer.new :name => 'outer', :inner => nil
|
108
|
+
end
|
109
|
+
|
110
|
+
def client_container
|
111
|
+
50
|
112
|
+
end
|
113
|
+
|
114
|
+
def named_parameters
|
115
|
+
@value_named_parameters = @method_params
|
116
|
+
end
|
117
|
+
|
118
|
+
def thrower
|
119
|
+
raise "Hi"
|
120
|
+
end
|
121
|
+
|
122
|
+
def user_return
|
123
|
+
User.find(1)
|
124
|
+
end
|
125
|
+
|
126
|
+
def with_model_return
|
127
|
+
WithModel.new :user => User.find(1), :users => User.find(:all)
|
128
|
+
end
|
129
|
+
|
130
|
+
def scoped_model_return
|
131
|
+
Accounting::User.find(1)
|
132
|
+
end
|
133
|
+
|
134
|
+
def multi_dim_return
|
135
|
+
WithMultiDimArray.new :pref => [%w{pref1 value1}, %w{pref2 value2}]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class AbstractClientLet < WEBrick::HTTPServlet::AbstractServlet
|
140
|
+
def initialize(controller)
|
141
|
+
@controller = controller
|
142
|
+
end
|
143
|
+
|
144
|
+
def get_instance(*args)
|
145
|
+
self
|
146
|
+
end
|
147
|
+
|
148
|
+
def require_path_info?
|
149
|
+
false
|
150
|
+
end
|
151
|
+
|
152
|
+
def do_GET(req, res)
|
153
|
+
raise WEBrick::HTTPStatus::MethodNotAllowed, "GET request not allowed."
|
154
|
+
end
|
155
|
+
|
156
|
+
def do_POST(req, res)
|
157
|
+
raise NotImplementedError
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
class AbstractServer
|
162
|
+
include ClientTest
|
163
|
+
include Singleton
|
164
|
+
attr :container
|
165
|
+
def initialize
|
166
|
+
@container = Container.new
|
167
|
+
@clientlet = create_clientlet(@container)
|
168
|
+
log = WEBrick::BasicLog.new(NullLogOut.new)
|
169
|
+
@server = WEBrick::HTTPServer.new(:Port => server_port, :Logger => log, :AccessLog => [])
|
170
|
+
@server.mount('/', @clientlet)
|
171
|
+
@thr = Thread.new { @server.start }
|
172
|
+
until @server.status == :Running; end
|
173
|
+
at_exit { @server.stop; @thr.join }
|
174
|
+
end
|
175
|
+
|
176
|
+
protected
|
177
|
+
def create_clientlet
|
178
|
+
raise NotImplementedError
|
179
|
+
end
|
180
|
+
|
181
|
+
def server_port
|
182
|
+
raise NotImplementedError
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,550 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'abstract_unit'
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
class ActionController::Base; def rescue_action(e) raise e end; end
|
6
|
+
|
7
|
+
module DispatcherTest
|
8
|
+
Utf8String = "One World Caf\303\251"
|
9
|
+
WsdlNamespace = 'http://rubyonrails.com/some/namespace'
|
10
|
+
|
11
|
+
class Node < ActiveRecord::Base
|
12
|
+
def initialize(*args)
|
13
|
+
super(*args)
|
14
|
+
@new_record = false
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def name
|
19
|
+
"DispatcherTest::Node"
|
20
|
+
end
|
21
|
+
|
22
|
+
def columns(*args)
|
23
|
+
[
|
24
|
+
ActiveRecord::ConnectionAdapters::Column.new('id', 0, 'int'),
|
25
|
+
ActiveRecord::ConnectionAdapters::Column.new('name', nil, 'string'),
|
26
|
+
ActiveRecord::ConnectionAdapters::Column.new('description', nil, 'string'),
|
27
|
+
]
|
28
|
+
end
|
29
|
+
|
30
|
+
def connection
|
31
|
+
self
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Person < ActionWebService::Struct
|
37
|
+
member :id, :int
|
38
|
+
member :name, :string
|
39
|
+
|
40
|
+
def ==(other)
|
41
|
+
self.id == other.id && self.name == other.name
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class API < ActionWebService::API::Base
|
46
|
+
api_method :add, :expects => [:int, :int], :returns => [:int]
|
47
|
+
api_method :interceptee
|
48
|
+
api_method :struct_return, :returns => [[Node]]
|
49
|
+
api_method :void
|
50
|
+
end
|
51
|
+
|
52
|
+
class DirectAPI < ActionWebService::API::Base
|
53
|
+
api_method :add, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int]
|
54
|
+
api_method :add2, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int]
|
55
|
+
api_method :before_filtered
|
56
|
+
api_method :after_filtered, :returns => [[:int]]
|
57
|
+
api_method :struct_return, :returns => [[Node]]
|
58
|
+
api_method :struct_pass, :expects => [{:person => Person}]
|
59
|
+
api_method :base_struct_return, :returns => [[Person]]
|
60
|
+
api_method :hash_struct_return, :returns => [[Person]]
|
61
|
+
api_method :thrower
|
62
|
+
api_method :void
|
63
|
+
api_method :test_utf8, :returns => [:string]
|
64
|
+
api_method :hex, :expects => [:base64], :returns => [:string]
|
65
|
+
api_method :unhex, :expects => [:string], :returns => [:base64]
|
66
|
+
api_method :time, :expects => [:time], :returns => [:time]
|
67
|
+
end
|
68
|
+
|
69
|
+
class VirtualAPI < ActionWebService::API::Base
|
70
|
+
default_api_method :fallback
|
71
|
+
end
|
72
|
+
|
73
|
+
class Service < ActionWebService::Base
|
74
|
+
web_service_api API
|
75
|
+
|
76
|
+
before_invocation :do_intercept, :only => [:interceptee]
|
77
|
+
|
78
|
+
attr :added
|
79
|
+
attr :intercepted
|
80
|
+
attr :void_called
|
81
|
+
|
82
|
+
def initialize
|
83
|
+
@void_called = false
|
84
|
+
end
|
85
|
+
|
86
|
+
def add(a, b)
|
87
|
+
@added = a + b
|
88
|
+
end
|
89
|
+
|
90
|
+
def interceptee
|
91
|
+
@intercepted = false
|
92
|
+
end
|
93
|
+
|
94
|
+
def struct_return
|
95
|
+
n1 = Node.new('id' => 1, 'name' => 'node1', 'description' => 'Node 1')
|
96
|
+
n2 = Node.new('id' => 2, 'name' => 'node2', 'description' => 'Node 2')
|
97
|
+
[n1, n2]
|
98
|
+
end
|
99
|
+
|
100
|
+
def void(*args)
|
101
|
+
@void_called = args
|
102
|
+
end
|
103
|
+
|
104
|
+
def do_intercept(name, args)
|
105
|
+
[false, "permission denied"]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class MTAPI < ActionWebService::API::Base
|
110
|
+
inflect_names false
|
111
|
+
api_method :getCategories, :returns => [[:string]]
|
112
|
+
api_method :bool, :returns => [:bool]
|
113
|
+
api_method :alwaysFail
|
114
|
+
api_method :person, :returns => [Person]
|
115
|
+
end
|
116
|
+
|
117
|
+
class BloggerAPI < ActionWebService::API::Base
|
118
|
+
inflect_names false
|
119
|
+
api_method :getCategories, :returns => [[:string]]
|
120
|
+
api_method :str, :expects => [:int], :returns => [:string]
|
121
|
+
api_method :alwaysFail
|
122
|
+
end
|
123
|
+
|
124
|
+
class MTService < ActionWebService::Base
|
125
|
+
web_service_api MTAPI
|
126
|
+
|
127
|
+
def getCategories
|
128
|
+
["mtCat1", "mtCat2"]
|
129
|
+
end
|
130
|
+
|
131
|
+
def bool
|
132
|
+
'y'
|
133
|
+
end
|
134
|
+
|
135
|
+
def alwaysFail
|
136
|
+
raise "MT AlwaysFail"
|
137
|
+
end
|
138
|
+
|
139
|
+
def person
|
140
|
+
Person.new('id' => 1, 'name' => 'person1')
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class BloggerService < ActionWebService::Base
|
145
|
+
web_service_api BloggerAPI
|
146
|
+
|
147
|
+
def getCategories
|
148
|
+
["bloggerCat1", "bloggerCat2"]
|
149
|
+
end
|
150
|
+
|
151
|
+
def str(int)
|
152
|
+
unless int.is_a?(Integer)
|
153
|
+
raise "Not an integer!"
|
154
|
+
end
|
155
|
+
500 + int
|
156
|
+
end
|
157
|
+
|
158
|
+
def alwaysFail
|
159
|
+
raise "Blogger AlwaysFail"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
class AbstractController < ActionController::Base
|
164
|
+
acts_as_web_service
|
165
|
+
def generate_wsdl
|
166
|
+
self.request ||= ::ActionController::TestRequest.new
|
167
|
+
to_wsdl
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
class DelegatedController < AbstractController
|
172
|
+
web_service_dispatching_mode :delegated
|
173
|
+
wsdl_namespace WsdlNamespace
|
174
|
+
|
175
|
+
web_service(:test_service) { @service ||= Service.new; @service }
|
176
|
+
end
|
177
|
+
|
178
|
+
class LayeredController < AbstractController
|
179
|
+
web_service_dispatching_mode :layered
|
180
|
+
wsdl_namespace WsdlNamespace
|
181
|
+
|
182
|
+
web_service(:mt) { @mt_service ||= MTService.new; @mt_service }
|
183
|
+
web_service(:blogger) { @blogger_service ||= BloggerService.new; @blogger_service }
|
184
|
+
end
|
185
|
+
|
186
|
+
class DirectController < AbstractController
|
187
|
+
web_service_api DirectAPI
|
188
|
+
web_service_dispatching_mode :direct
|
189
|
+
wsdl_namespace WsdlNamespace
|
190
|
+
|
191
|
+
before_invocation :alwaysfail, :only => [:before_filtered]
|
192
|
+
after_invocation :alwaysok, :only => [:after_filtered]
|
193
|
+
|
194
|
+
attr :added
|
195
|
+
attr :added2
|
196
|
+
attr :before_filter_called
|
197
|
+
attr :before_filter_target_called
|
198
|
+
attr :after_filter_called
|
199
|
+
attr :after_filter_target_called
|
200
|
+
attr :void_called
|
201
|
+
attr :struct_pass_value
|
202
|
+
|
203
|
+
def initialize
|
204
|
+
@before_filter_called = false
|
205
|
+
@before_filter_target_called = false
|
206
|
+
@after_filter_called = false
|
207
|
+
@after_filter_target_called = false
|
208
|
+
@void_called = false
|
209
|
+
@struct_pass_value = false
|
210
|
+
end
|
211
|
+
|
212
|
+
def add
|
213
|
+
@added = params['a'] + params['b']
|
214
|
+
end
|
215
|
+
|
216
|
+
def add2(a, b)
|
217
|
+
@added2 = a + b
|
218
|
+
end
|
219
|
+
|
220
|
+
def before_filtered
|
221
|
+
@before_filter_target_called = true
|
222
|
+
end
|
223
|
+
|
224
|
+
def after_filtered
|
225
|
+
@after_filter_target_called = true
|
226
|
+
[5, 6, 7]
|
227
|
+
end
|
228
|
+
|
229
|
+
def thrower
|
230
|
+
raise "Hi, I'm an exception"
|
231
|
+
end
|
232
|
+
|
233
|
+
def struct_return
|
234
|
+
n1 = Node.new('id' => 1, 'name' => 'node1', 'description' => 'Node 1')
|
235
|
+
n2 = Node.new('id' => 2, 'name' => 'node2', 'description' => 'Node 2')
|
236
|
+
[n1, n2]
|
237
|
+
end
|
238
|
+
|
239
|
+
def struct_pass(person)
|
240
|
+
@struct_pass_value = person
|
241
|
+
end
|
242
|
+
|
243
|
+
def base_struct_return
|
244
|
+
p1 = Person.new('id' => 1, 'name' => 'person1')
|
245
|
+
p2 = Person.new('id' => 2, 'name' => 'person2')
|
246
|
+
[p1, p2]
|
247
|
+
end
|
248
|
+
|
249
|
+
def hash_struct_return
|
250
|
+
p1 = { :id => '1', 'name' => 'test' }
|
251
|
+
p2 = { 'id' => '2', :name => 'person2' }
|
252
|
+
[p1, p2]
|
253
|
+
end
|
254
|
+
|
255
|
+
def void
|
256
|
+
@void_called = @method_params
|
257
|
+
end
|
258
|
+
|
259
|
+
def test_utf8
|
260
|
+
Utf8String
|
261
|
+
end
|
262
|
+
|
263
|
+
def hex(s)
|
264
|
+
return s.unpack("H*")[0]
|
265
|
+
end
|
266
|
+
|
267
|
+
def unhex(s)
|
268
|
+
return [s].pack("H*")
|
269
|
+
end
|
270
|
+
|
271
|
+
def time(t)
|
272
|
+
t
|
273
|
+
end
|
274
|
+
|
275
|
+
protected
|
276
|
+
def alwaysfail(method_name, params)
|
277
|
+
@before_filter_called = true
|
278
|
+
false
|
279
|
+
end
|
280
|
+
|
281
|
+
def alwaysok(method_name, params, return_value)
|
282
|
+
@after_filter_called = true
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
class VirtualController < AbstractController
|
287
|
+
web_service_api VirtualAPI
|
288
|
+
wsdl_namespace WsdlNamespace
|
289
|
+
|
290
|
+
def fallback
|
291
|
+
"fallback!"
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
module DispatcherCommonTests
|
297
|
+
def test_direct_dispatching
|
298
|
+
assert_equal(70, do_method_call(@direct_controller, 'Add', 20, 50))
|
299
|
+
assert_equal(70, @direct_controller.added)
|
300
|
+
assert_equal(50, do_method_call(@direct_controller, 'Add2', 25, 25))
|
301
|
+
assert_equal(50, @direct_controller.added2)
|
302
|
+
assert(@direct_controller.void_called == false)
|
303
|
+
assert(do_method_call(@direct_controller, 'Void', 3, 4, 5).nil?)
|
304
|
+
assert(@direct_controller.void_called == [])
|
305
|
+
result = do_method_call(@direct_controller, 'BaseStructReturn')
|
306
|
+
assert(result[0].is_a?(DispatcherTest::Person))
|
307
|
+
assert(result[1].is_a?(DispatcherTest::Person))
|
308
|
+
assert_equal("cafe", do_method_call(@direct_controller, 'Hex', "\xca\xfe"))
|
309
|
+
assert_equal("\xca\xfe", do_method_call(@direct_controller, 'Unhex', "cafe"))
|
310
|
+
time = Time.gm(1998, "Feb", 02, 15, 12, 01)
|
311
|
+
assert_equal(time, do_method_call(@direct_controller, 'Time', time))
|
312
|
+
end
|
313
|
+
|
314
|
+
def test_direct_entrypoint
|
315
|
+
assert(@direct_controller.respond_to?(:api))
|
316
|
+
end
|
317
|
+
|
318
|
+
def test_virtual_dispatching
|
319
|
+
assert_equal("fallback!", do_method_call(@virtual_controller, 'VirtualOne'))
|
320
|
+
assert_equal("fallback!", do_method_call(@virtual_controller, 'VirtualTwo'))
|
321
|
+
end
|
322
|
+
|
323
|
+
def test_direct_filtering
|
324
|
+
assert_equal(false, @direct_controller.before_filter_called)
|
325
|
+
assert_equal(false, @direct_controller.before_filter_target_called)
|
326
|
+
do_method_call(@direct_controller, 'BeforeFiltered')
|
327
|
+
assert_equal(true, @direct_controller.before_filter_called)
|
328
|
+
assert_equal(false, @direct_controller.before_filter_target_called)
|
329
|
+
assert_equal(false, @direct_controller.after_filter_called)
|
330
|
+
assert_equal(false, @direct_controller.after_filter_target_called)
|
331
|
+
assert_equal([5, 6, 7], do_method_call(@direct_controller, 'AfterFiltered'))
|
332
|
+
assert_equal(true, @direct_controller.after_filter_called)
|
333
|
+
assert_equal(true, @direct_controller.after_filter_target_called)
|
334
|
+
end
|
335
|
+
|
336
|
+
def test_delegated_dispatching
|
337
|
+
assert_equal(130, do_method_call(@delegated_controller, 'Add', 50, 80))
|
338
|
+
service = @delegated_controller.web_service_object(:test_service)
|
339
|
+
assert_equal(130, service.added)
|
340
|
+
@delegated_controller.web_service_exception_reporting = true
|
341
|
+
assert(service.intercepted.nil?)
|
342
|
+
result = do_method_call(@delegated_controller, 'Interceptee')
|
343
|
+
assert(service.intercepted.nil?)
|
344
|
+
assert(is_exception?(result))
|
345
|
+
assert_match(/permission denied/, exception_message(result))
|
346
|
+
result = do_method_call(@delegated_controller, 'NonExistentMethod')
|
347
|
+
assert(is_exception?(result))
|
348
|
+
assert_match(/NonExistentMethod/, exception_message(result))
|
349
|
+
assert(service.void_called == false)
|
350
|
+
assert(do_method_call(@delegated_controller, 'Void', 3, 4, 5).nil?)
|
351
|
+
assert(service.void_called == [])
|
352
|
+
end
|
353
|
+
|
354
|
+
def test_garbage_request
|
355
|
+
[@direct_controller, @delegated_controller].each do |controller|
|
356
|
+
controller.class.web_service_exception_reporting = true
|
357
|
+
send_garbage_request = lambda do
|
358
|
+
service_name = service_name(controller)
|
359
|
+
request = protocol.encode_action_pack_request(service_name, 'broken, method, name!', 'broken request body', :request_class => ActionController::TestRequest)
|
360
|
+
response = ActionController::TestResponse.new
|
361
|
+
controller.process(request, response)
|
362
|
+
# puts response.body
|
363
|
+
assert(response.status =~ /^500/)
|
364
|
+
end
|
365
|
+
send_garbage_request.call
|
366
|
+
controller.class.web_service_exception_reporting = false
|
367
|
+
send_garbage_request.call
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
def test_exception_marshaling
|
372
|
+
@direct_controller.web_service_exception_reporting = true
|
373
|
+
result = do_method_call(@direct_controller, 'Thrower')
|
374
|
+
assert(is_exception?(result))
|
375
|
+
assert_equal("Hi, I'm an exception", exception_message(result))
|
376
|
+
@direct_controller.web_service_exception_reporting = false
|
377
|
+
result = do_method_call(@direct_controller, 'Thrower')
|
378
|
+
assert(exception_message(result) != "Hi, I'm an exception")
|
379
|
+
end
|
380
|
+
|
381
|
+
def test_ar_struct_return
|
382
|
+
[@direct_controller, @delegated_controller].each do |controller|
|
383
|
+
result = do_method_call(controller, 'StructReturn')
|
384
|
+
assert(result[0].is_a?(DispatcherTest::Node))
|
385
|
+
assert(result[1].is_a?(DispatcherTest::Node))
|
386
|
+
assert_equal('node1', result[0].name)
|
387
|
+
assert_equal('node2', result[1].name)
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
def test_casting
|
392
|
+
assert_equal 70, do_method_call(@direct_controller, 'Add', "50", "20")
|
393
|
+
assert_equal false, @direct_controller.struct_pass_value
|
394
|
+
person = DispatcherTest::Person.new(:id => 1, :name => 'test')
|
395
|
+
result = do_method_call(@direct_controller, 'StructPass', person)
|
396
|
+
assert(nil == result || true == result)
|
397
|
+
assert_equal person, @direct_controller.struct_pass_value
|
398
|
+
assert !person.equal?(@direct_controller.struct_pass_value)
|
399
|
+
result = do_method_call(@direct_controller, 'StructPass', {'id' => '1', 'name' => 'test'})
|
400
|
+
case
|
401
|
+
when soap?
|
402
|
+
assert_equal(person, @direct_controller.struct_pass_value)
|
403
|
+
assert !person.equal?(@direct_controller.struct_pass_value)
|
404
|
+
when xmlrpc?
|
405
|
+
assert_equal(person, @direct_controller.struct_pass_value)
|
406
|
+
assert !person.equal?(@direct_controller.struct_pass_value)
|
407
|
+
end
|
408
|
+
assert_equal person, do_method_call(@direct_controller, 'HashStructReturn')[0]
|
409
|
+
result = do_method_call(@direct_controller, 'StructPass', {'id' => '1', 'name' => 'test', 'nonexistent_attribute' => 'value'})
|
410
|
+
case
|
411
|
+
when soap?
|
412
|
+
assert_equal(person, @direct_controller.struct_pass_value)
|
413
|
+
assert !person.equal?(@direct_controller.struct_pass_value)
|
414
|
+
when xmlrpc?
|
415
|
+
assert_equal(person, @direct_controller.struct_pass_value)
|
416
|
+
assert !person.equal?(@direct_controller.struct_pass_value)
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
def test_logging
|
421
|
+
buf = ""
|
422
|
+
ActionController::Base.logger = Logger.new(StringIO.new(buf))
|
423
|
+
test_casting
|
424
|
+
test_garbage_request
|
425
|
+
test_exception_marshaling
|
426
|
+
ActionController::Base.logger = nil
|
427
|
+
assert_match /Web Service Response/, buf
|
428
|
+
assert_match /Web Service Request/, buf
|
429
|
+
end
|
430
|
+
|
431
|
+
def test_allowed_http_methods
|
432
|
+
webservice_api = @direct_controller.class.web_service_api
|
433
|
+
original_allowed_http_methods = webservice_api.allowed_http_methods
|
434
|
+
|
435
|
+
# check defaults
|
436
|
+
assert_equal false, http_method_allowed?(:get)
|
437
|
+
assert_equal false, http_method_allowed?(:head)
|
438
|
+
assert_equal false, http_method_allowed?(:put)
|
439
|
+
assert_equal false, http_method_allowed?(:delete)
|
440
|
+
assert_equal true, http_method_allowed?(:post)
|
441
|
+
|
442
|
+
# allow get and post
|
443
|
+
webservice_api.allowed_http_methods = [ :get, :post ]
|
444
|
+
assert_equal true, http_method_allowed?(:get)
|
445
|
+
assert_equal true, http_method_allowed?(:post)
|
446
|
+
|
447
|
+
# allow get only
|
448
|
+
webservice_api.allowed_http_methods = [ :get ]
|
449
|
+
assert_equal true, http_method_allowed?(:get)
|
450
|
+
assert_equal false, http_method_allowed?(:post)
|
451
|
+
|
452
|
+
# allow delete only
|
453
|
+
webservice_api.allowed_http_methods = [ 'DELETE' ]
|
454
|
+
assert_equal false, http_method_allowed?(:get)
|
455
|
+
assert_equal false, http_method_allowed?(:head)
|
456
|
+
assert_equal false, http_method_allowed?(:post)
|
457
|
+
assert_equal false, http_method_allowed?(:put)
|
458
|
+
assert_equal true, http_method_allowed?(:delete)
|
459
|
+
|
460
|
+
ensure
|
461
|
+
webservice_api.allowed_http_methods = original_allowed_http_methods
|
462
|
+
end
|
463
|
+
|
464
|
+
protected
|
465
|
+
def service_name(container)
|
466
|
+
raise NotImplementedError
|
467
|
+
end
|
468
|
+
|
469
|
+
def exception_message(obj)
|
470
|
+
raise NotImplementedError
|
471
|
+
end
|
472
|
+
|
473
|
+
def is_exception?(obj)
|
474
|
+
raise NotImplementedError
|
475
|
+
end
|
476
|
+
|
477
|
+
def protocol
|
478
|
+
@protocol
|
479
|
+
end
|
480
|
+
|
481
|
+
def soap?
|
482
|
+
protocol.is_a? ActionWebService::Protocol::Soap::SoapProtocol
|
483
|
+
end
|
484
|
+
|
485
|
+
def xmlrpc?
|
486
|
+
protocol.is_a? ActionWebService::Protocol::XmlRpc::XmlRpcProtocol
|
487
|
+
end
|
488
|
+
|
489
|
+
def do_method_call(container, public_method_name, *params)
|
490
|
+
request_env = {}
|
491
|
+
mode = container.web_service_dispatching_mode
|
492
|
+
case mode
|
493
|
+
when :direct
|
494
|
+
service_name = service_name(container)
|
495
|
+
api = container.class.web_service_api
|
496
|
+
method = api.public_api_method_instance(public_method_name)
|
497
|
+
when :delegated
|
498
|
+
service_name = service_name(container)
|
499
|
+
api = container.web_service_object(service_name).class.web_service_api
|
500
|
+
method = api.public_api_method_instance(public_method_name)
|
501
|
+
when :layered
|
502
|
+
service_name = nil
|
503
|
+
real_method_name = nil
|
504
|
+
if public_method_name =~ /^([^\.]+)\.(.*)$/
|
505
|
+
service_name = $1
|
506
|
+
real_method_name = $2
|
507
|
+
end
|
508
|
+
if soap?
|
509
|
+
public_method_name = real_method_name
|
510
|
+
request_env['HTTP_SOAPACTION'] = "/soap/#{service_name}/#{real_method_name}"
|
511
|
+
end
|
512
|
+
api = container.web_service_object(service_name.to_sym).class.web_service_api rescue nil
|
513
|
+
method = api.public_api_method_instance(real_method_name) rescue nil
|
514
|
+
service_name = self.service_name(container)
|
515
|
+
end
|
516
|
+
protocol.register_api(api)
|
517
|
+
virtual = false
|
518
|
+
unless method
|
519
|
+
virtual = true
|
520
|
+
method ||= ActionWebService::API::Method.new(public_method_name.underscore.to_sym, public_method_name, nil, nil)
|
521
|
+
end
|
522
|
+
body = protocol.encode_request(public_method_name, params.dup, method.expects)
|
523
|
+
# puts body
|
524
|
+
ap_request = protocol.encode_action_pack_request(service_name, public_method_name, body, :request_class => ActionController::TestRequest)
|
525
|
+
ap_request.env.update(request_env)
|
526
|
+
ap_response = ActionController::TestResponse.new
|
527
|
+
container.process(ap_request, ap_response)
|
528
|
+
# puts ap_response.body
|
529
|
+
@response_body = ap_response.body
|
530
|
+
public_method_name, return_value = protocol.decode_response(ap_response.body)
|
531
|
+
unless is_exception?(return_value) || virtual
|
532
|
+
return_value = method.cast_returns(return_value)
|
533
|
+
end
|
534
|
+
if soap?
|
535
|
+
# http://dev.rubyonrails.com/changeset/920
|
536
|
+
assert_match(/Response$/, public_method_name) unless public_method_name == "fault"
|
537
|
+
end
|
538
|
+
return_value
|
539
|
+
end
|
540
|
+
|
541
|
+
def http_method_allowed?(method)
|
542
|
+
method = method.to_s.upcase
|
543
|
+
test_request = ActionController::TestRequest.new
|
544
|
+
test_request.action = 'api'
|
545
|
+
test_response = ActionController::TestResponse.new
|
546
|
+
test_request.env['REQUEST_METHOD'] = method
|
547
|
+
result = @direct_controller.process(test_request, test_response)
|
548
|
+
result.body =~ /(GET|POST|PUT|DELETE|TRACE|CONNECT) not supported/ ? false : true
|
549
|
+
end
|
550
|
+
end
|