actionwebservice 0.8.1 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +20 -0
- data/README +19 -0
- data/Rakefile +5 -4
- data/lib/action_web_service/dispatcher/abstract.rb +68 -6
- data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +12 -9
- data/lib/action_web_service/protocol/abstract.rb +1 -1
- data/lib/action_web_service/protocol/soap_protocol.rb +33 -15
- data/lib/action_web_service/protocol/xmlrpc_protocol.rb +9 -0
- data/lib/action_web_service/scaffolding.rb +13 -4
- data/lib/action_web_service/test_invoke.rb +2 -1
- data/lib/action_web_service/version.rb +9 -0
- data/test/abstract_dispatcher.rb +32 -10
- data/test/dispatcher_action_controller_soap_test.rb +18 -9
- data/test/dispatcher_action_controller_xmlrpc_test.rb +23 -0
- metadata +6 -5
data/CHANGELOG
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
*0.9.1* (October 19th, 2005)
|
2
|
+
|
3
|
+
* Upgraded to Action Pack 1.10.1 and Active Record 1.12.1
|
4
|
+
|
5
|
+
|
6
|
+
*0.9.0* (October 16th, 2005)
|
7
|
+
|
8
|
+
* Fix invalid XML request generation bug in test_invoke [Ken Barker]
|
9
|
+
|
10
|
+
* Add XML-RPC 'system.multicall' support #1941 [jbonnar]
|
11
|
+
|
12
|
+
* Fix duplicate XSD entries for custom types shared across delegated/layered services #1729 [Tyler Kovacs]
|
13
|
+
|
14
|
+
* Allow multiple invocations in the same test method #1720 [dkhawk]
|
15
|
+
|
16
|
+
* Added ActionWebService::API::Base.soap_client and ActionWebService::API::Base.xmlrpc_client helper methods to create the internal clients for an API, useful for testing from ./script/console
|
17
|
+
|
18
|
+
* ActionWebService now always returns UTF-8 responses.
|
19
|
+
|
20
|
+
|
1
21
|
*0.8.1* (11 July, 2005)
|
2
22
|
|
3
23
|
* Fix scaffolding for Action Pack controller changes
|
data/README
CHANGED
@@ -215,6 +215,25 @@ custom types and message definition types:
|
|
215
215
|
The default namespace used is 'urn:ActionWebService', if you don't supply
|
216
216
|
one.
|
217
217
|
|
218
|
+
|
219
|
+
== ActionWebService and UTF-8
|
220
|
+
|
221
|
+
If you're going to be sending back strings containing non-ASCII UTF-8
|
222
|
+
characters using the <tt>:string</tt> data type, you need to make sure that
|
223
|
+
Ruby is using UTF-8 as the default encoding for its strings.
|
224
|
+
|
225
|
+
The default in Ruby to use US-ASCII encoding for strings, which causes a string
|
226
|
+
validation check in the Ruby SOAP library to fail and your string to be sent
|
227
|
+
back as a Base-64 value, which may confuse clients that expected strings
|
228
|
+
because of the WSDL.
|
229
|
+
|
230
|
+
Two ways of doing setting the default string encoding are:
|
231
|
+
|
232
|
+
* Start Ruby using the <tt>-Ku</tt> command-line option to the Ruby executable
|
233
|
+
* Set the <tt>$KCODE</tt> flag in <tt>config/environment.rb</tt> to the
|
234
|
+
string <tt>'UTF8'</tt>
|
235
|
+
|
236
|
+
|
218
237
|
== Testing your APIs
|
219
238
|
|
220
239
|
|
data/Rakefile
CHANGED
@@ -6,10 +6,11 @@ require 'rake/packagetask'
|
|
6
6
|
require 'rake/gempackagetask'
|
7
7
|
require 'rake/contrib/rubyforgepublisher'
|
8
8
|
require 'fileutils'
|
9
|
+
require File.join(File.dirname(__FILE__), 'lib', 'action_web_service', 'version')
|
9
10
|
|
10
11
|
PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
|
11
12
|
PKG_NAME = 'actionwebservice'
|
12
|
-
PKG_VERSION =
|
13
|
+
PKG_VERSION = ActionWebService::Version::STRING + PKG_BUILD
|
13
14
|
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
14
15
|
PKG_DESTINATION = ENV["RAILS_PKG_DESTINATION"] || "../#{PKG_NAME}"
|
15
16
|
|
@@ -62,9 +63,9 @@ spec = Gem::Specification.new do |s|
|
|
62
63
|
s.rubyforge_project = "aws"
|
63
64
|
s.homepage = "http://www.rubyonrails.org"
|
64
65
|
|
65
|
-
s.add_dependency('actionpack', '= 1.
|
66
|
-
s.add_dependency('activerecord', '= 1.
|
67
|
-
s.add_dependency('activesupport', '= 1.
|
66
|
+
s.add_dependency('actionpack', '= 1.10.1' + PKG_BUILD)
|
67
|
+
s.add_dependency('activerecord', '= 1.12.1' + PKG_BUILD)
|
68
|
+
s.add_dependency('activesupport', '= 1.2.1' + PKG_BUILD)
|
68
69
|
|
69
70
|
s.has_rdoc = true
|
70
71
|
s.requirements << 'none'
|
@@ -16,11 +16,10 @@ module ActionWebService # :nodoc:
|
|
16
16
|
private
|
17
17
|
def invoke_web_service_request(protocol_request)
|
18
18
|
invocation = web_service_invocation(protocol_request)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
web_service_delegated_invoke(invocation)
|
19
|
+
if invocation.is_a?(Array) && protocol_request.protocol.is_a?(Protocol::XmlRpc::XmlRpcProtocol)
|
20
|
+
xmlrpc_multicall_invoke(invocation)
|
21
|
+
else
|
22
|
+
web_service_invoke(invocation)
|
24
23
|
end
|
25
24
|
end
|
26
25
|
|
@@ -47,10 +46,47 @@ module ActionWebService # :nodoc:
|
|
47
46
|
if cancellation_reason
|
48
47
|
raise(DispatcherError, "request canceled: #{cancellation_reason}")
|
49
48
|
end
|
49
|
+
return_value
|
50
|
+
end
|
51
|
+
|
52
|
+
def web_service_invoke(invocation)
|
53
|
+
case web_service_dispatching_mode
|
54
|
+
when :direct
|
55
|
+
return_value = web_service_direct_invoke(invocation)
|
56
|
+
when :delegated, :layered
|
57
|
+
return_value = web_service_delegated_invoke(invocation)
|
58
|
+
end
|
50
59
|
web_service_create_response(invocation.protocol, invocation.protocol_options, invocation.api, invocation.api_method, return_value)
|
51
60
|
end
|
61
|
+
|
62
|
+
def xmlrpc_multicall_invoke(invocations)
|
63
|
+
responses = []
|
64
|
+
invocations.each do |invocation|
|
65
|
+
if invocation.is_a?(Hash)
|
66
|
+
responses << invocation
|
67
|
+
next
|
68
|
+
end
|
69
|
+
begin
|
70
|
+
case web_service_dispatching_mode
|
71
|
+
when :direct
|
72
|
+
return_value = web_service_direct_invoke(invocation)
|
73
|
+
when :delegated, :layered
|
74
|
+
return_value = web_service_delegated_invoke(invocation)
|
75
|
+
end
|
76
|
+
api_method = invocation.api_method
|
77
|
+
if invocation.api.has_api_method?(api_method.name)
|
78
|
+
return_value = api_method.cast_returns(return_value)
|
79
|
+
end
|
80
|
+
responses << [return_value]
|
81
|
+
rescue Exception => e
|
82
|
+
responses << { 'faultCode' => 3, 'faultString' => e.message }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
invocation = invocations[0]
|
86
|
+
invocation.protocol.encode_response('system.multicall', responses, nil, invocation.protocol_options)
|
87
|
+
end
|
52
88
|
|
53
|
-
def web_service_invocation(request)
|
89
|
+
def web_service_invocation(request, level = 0)
|
54
90
|
public_method_name = request.method_name
|
55
91
|
invocation = Invocation.new
|
56
92
|
invocation.protocol = request.protocol
|
@@ -70,6 +106,32 @@ module ActionWebService # :nodoc:
|
|
70
106
|
end
|
71
107
|
end
|
72
108
|
end
|
109
|
+
if invocation.protocol.is_a? Protocol::XmlRpc::XmlRpcProtocol
|
110
|
+
if public_method_name == 'multicall' && invocation.service_name == 'system'
|
111
|
+
if level > 0
|
112
|
+
raise(DispatcherError, "Recursive system.multicall invocations not allowed")
|
113
|
+
end
|
114
|
+
multicall = request.method_params.dup
|
115
|
+
unless multicall.is_a?(Array) && multicall[0].is_a?(Array)
|
116
|
+
raise(DispatcherError, "Malformed multicall (expected array of Hash elements)")
|
117
|
+
end
|
118
|
+
multicall = multicall[0]
|
119
|
+
return multicall.map do |item|
|
120
|
+
raise(DispatcherError, "Multicall elements must be Hash") unless item.is_a?(Hash)
|
121
|
+
raise(DispatcherError, "Multicall elements must contain a 'methodName' key") unless item.has_key?('methodName')
|
122
|
+
method_name = item['methodName']
|
123
|
+
params = item.has_key?('params') ? item['params'] : []
|
124
|
+
multicall_request = request.dup
|
125
|
+
multicall_request.method_name = method_name
|
126
|
+
multicall_request.method_params = params
|
127
|
+
begin
|
128
|
+
web_service_invocation(multicall_request, level + 1)
|
129
|
+
rescue Exception => e
|
130
|
+
{'faultCode' => 4, 'faultMessage' => e.message}
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
73
135
|
case web_service_dispatching_mode
|
74
136
|
when :direct
|
75
137
|
invocation.api = self.class.web_service_api
|
@@ -195,7 +195,7 @@ module ActionWebService # :nodoc:
|
|
195
195
|
custom_types = []
|
196
196
|
apis.values.each do |api, bindings|
|
197
197
|
bindings.each do |b|
|
198
|
-
custom_types << b
|
198
|
+
custom_types << b unless custom_types.include?(b)
|
199
199
|
end
|
200
200
|
end
|
201
201
|
|
@@ -347,29 +347,32 @@ module ActionWebService # :nodoc:
|
|
347
347
|
|
348
348
|
def register_api(api, marshaler)
|
349
349
|
bindings = {}
|
350
|
-
traverse_custom_types(api, marshaler) do |binding|
|
350
|
+
traverse_custom_types(api, marshaler, bindings) do |binding|
|
351
351
|
bindings[binding] = nil unless bindings.has_key?(binding)
|
352
352
|
element_binding = binding.element_binding
|
353
|
-
bindings[
|
353
|
+
bindings[element_binding] = nil if element_binding && !bindings.has_key?(element_binding)
|
354
354
|
end
|
355
355
|
bindings.keys
|
356
356
|
end
|
357
357
|
|
358
|
-
def traverse_custom_types(api, marshaler, &block)
|
358
|
+
def traverse_custom_types(api, marshaler, bindings, &block)
|
359
359
|
api.api_methods.each do |name, method|
|
360
360
|
expects, returns = method.expects, method.returns
|
361
|
-
expects.each{ |type| traverse_type(marshaler, type, &block) if type.custom? } if expects
|
362
|
-
returns.each{ |type| traverse_type(marshaler, type, &block) if type.custom? } if returns
|
361
|
+
expects.each{ |type| traverse_type(marshaler, type, bindings, &block) if type.custom? } if expects
|
362
|
+
returns.each{ |type| traverse_type(marshaler, type, bindings, &block) if type.custom? } if returns
|
363
363
|
end
|
364
364
|
end
|
365
365
|
|
366
|
-
def traverse_type(marshaler, type, &block)
|
367
|
-
|
366
|
+
def traverse_type(marshaler, type, bindings, &block)
|
367
|
+
binding = marshaler.register_type(type)
|
368
|
+
return if bindings.has_key?(binding)
|
369
|
+
bindings[binding] = nil
|
370
|
+
yield binding
|
368
371
|
if type.array?
|
369
372
|
yield marshaler.register_type(type.element_type)
|
370
373
|
type = type.element_type
|
371
374
|
end
|
372
|
-
type.each_member{ |name, type| traverse_type(marshaler, type, &block) } if type.structured?
|
375
|
+
type.each_member{ |name, type| traverse_type(marshaler, type, bindings, &block) } if type.structured?
|
373
376
|
end
|
374
377
|
end
|
375
378
|
end
|
@@ -1,7 +1,16 @@
|
|
1
1
|
require 'action_web_service/protocol/soap_protocol/marshaler'
|
2
2
|
require 'soap/streamHandler'
|
3
|
+
require 'action_web_service/client/soap_client'
|
3
4
|
|
4
5
|
module ActionWebService # :nodoc:
|
6
|
+
module API # :nodoc:
|
7
|
+
class Base # :nodoc:
|
8
|
+
def self.soap_client(endpoint_uri, options={})
|
9
|
+
ActionWebService::Client::Soap.new self, endpoint_uri, options
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
5
14
|
module Protocol # :nodoc:
|
6
15
|
module Soap # :nodoc:
|
7
16
|
def self.included(base)
|
@@ -11,7 +20,8 @@ module ActionWebService # :nodoc:
|
|
11
20
|
end
|
12
21
|
|
13
22
|
class SoapProtocol < AbstractProtocol # :nodoc:
|
14
|
-
|
23
|
+
AWSEncoding = 'UTF-8'
|
24
|
+
XSDEncoding = 'UTF8'
|
15
25
|
|
16
26
|
attr :marshaler
|
17
27
|
|
@@ -27,10 +37,10 @@ module ActionWebService # :nodoc:
|
|
27
37
|
def decode_action_pack_request(action_pack_request)
|
28
38
|
return nil unless soap_action = has_valid_soap_action?(action_pack_request)
|
29
39
|
service_name = action_pack_request.parameters['action']
|
30
|
-
|
40
|
+
input_encoding = parse_charset(action_pack_request.env['HTTP_CONTENT_TYPE'])
|
31
41
|
protocol_options = {
|
32
42
|
:soap_action => soap_action,
|
33
|
-
:charset =>
|
43
|
+
:charset => input_encoding
|
34
44
|
}
|
35
45
|
decode_request(action_pack_request.raw_post, service_name, protocol_options)
|
36
46
|
end
|
@@ -42,8 +52,7 @@ module ActionWebService # :nodoc:
|
|
42
52
|
end
|
43
53
|
|
44
54
|
def decode_request(raw_request, service_name, protocol_options={})
|
45
|
-
|
46
|
-
envelope = SOAP::Processor.unmarshal(raw_request, :charset => charset)
|
55
|
+
envelope = SOAP::Processor.unmarshal(raw_request, :charset => protocol_options[:charset])
|
47
56
|
unless envelope
|
48
57
|
raise ProtocolError, "Failed to parse SOAP request message"
|
49
58
|
end
|
@@ -109,8 +118,17 @@ module ActionWebService # :nodoc:
|
|
109
118
|
end
|
110
119
|
end
|
111
120
|
envelope = create_soap_envelope(response)
|
112
|
-
|
113
|
-
|
121
|
+
|
122
|
+
# FIXME: This is not thread-safe, but StringFactory_ in SOAP4R only
|
123
|
+
# reads target encoding from the XSD::Charset.encoding variable.
|
124
|
+
# This is required to ensure $KCODE strings are converted
|
125
|
+
# correctly to UTF-8 for any values of $KCODE.
|
126
|
+
previous_encoding = XSD::Charset.encoding
|
127
|
+
XSD::Charset.encoding = XSDEncoding
|
128
|
+
response_body = SOAP::Processor.marshal(envelope, :charset => AWSEncoding)
|
129
|
+
XSD::Charset.encoding = previous_encoding
|
130
|
+
|
131
|
+
Response.new(response_body, "text/xml; charset=#{AWSEncoding}", return_value)
|
114
132
|
end
|
115
133
|
|
116
134
|
def protocol_client(api, protocol_name, endpoint_uri, options={})
|
@@ -138,20 +156,20 @@ module ActionWebService # :nodoc:
|
|
138
156
|
soap_action
|
139
157
|
end
|
140
158
|
|
159
|
+
def create_soap_envelope(body)
|
160
|
+
header = SOAP::SOAPHeader.new
|
161
|
+
body = SOAP::SOAPBody.new(body)
|
162
|
+
SOAP::SOAPEnvelope.new(header, body)
|
163
|
+
end
|
164
|
+
|
141
165
|
def parse_charset(content_type)
|
142
|
-
return
|
166
|
+
return AWSEncoding if content_type.nil?
|
143
167
|
if /^text\/xml(?:\s*;\s*charset=([^"]+|"[^"]+"))$/i =~ content_type
|
144
168
|
$1
|
145
169
|
else
|
146
|
-
|
170
|
+
AWSEncoding
|
147
171
|
end
|
148
172
|
end
|
149
|
-
|
150
|
-
def create_soap_envelope(body)
|
151
|
-
header = SOAP::SOAPHeader.new
|
152
|
-
body = SOAP::SOAPBody.new(body)
|
153
|
-
SOAP::SOAPEnvelope.new(header, body)
|
154
|
-
end
|
155
173
|
end
|
156
174
|
end
|
157
175
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'xmlrpc/marshal'
|
2
|
+
require 'action_web_service/client/xmlrpc_client'
|
2
3
|
|
3
4
|
module XMLRPC # :nodoc:
|
4
5
|
class FaultException # :nodoc:
|
@@ -7,6 +8,14 @@ module XMLRPC # :nodoc:
|
|
7
8
|
end
|
8
9
|
|
9
10
|
module ActionWebService # :nodoc:
|
11
|
+
module API # :nodoc:
|
12
|
+
class Base # :nodoc:
|
13
|
+
def self.xmlrpc_client(endpoint_uri, options={})
|
14
|
+
ActionWebService::Client::XmlRpc.new self, endpoint_uri, options
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
10
19
|
module Protocol # :nodoc:
|
11
20
|
module XmlRpc # :nodoc:
|
12
21
|
def self.included(base)
|
@@ -40,7 +40,7 @@ module ActionWebService
|
|
40
40
|
# can then be used as the entry point for invoking API methods from a web browser.
|
41
41
|
def web_service_scaffold(action_name)
|
42
42
|
add_template_helper(Helpers)
|
43
|
-
module_eval <<-
|
43
|
+
module_eval <<-"end_eval", __FILE__, __LINE__
|
44
44
|
def #{action_name}
|
45
45
|
if request.method == :get
|
46
46
|
setup_invocation_assigns
|
@@ -112,8 +112,17 @@ module ActionWebService
|
|
112
112
|
def render_invocation_scaffold(action)
|
113
113
|
customized_template = "\#{self.class.controller_path}/#{action_name}/\#{action}"
|
114
114
|
default_template = scaffold_path(action)
|
115
|
-
|
116
|
-
|
115
|
+
if template_exists?(customized_template)
|
116
|
+
content = @template.render_file(customized_template)
|
117
|
+
else
|
118
|
+
content = @template.render_file(default_template, false)
|
119
|
+
end
|
120
|
+
@template.instance_variable_set("@content_for_layout", content)
|
121
|
+
if self.active_layout.nil?
|
122
|
+
render_file(scaffold_path("layout"))
|
123
|
+
else
|
124
|
+
render_file(self.active_layout, "200 OK", true)
|
125
|
+
end
|
117
126
|
end
|
118
127
|
|
119
128
|
def scaffold_path(template_name)
|
@@ -159,7 +168,7 @@ module ActionWebService
|
|
159
168
|
rescue_action(exception)
|
160
169
|
true
|
161
170
|
end
|
162
|
-
|
171
|
+
end_eval
|
163
172
|
end
|
164
173
|
end
|
165
174
|
|
@@ -29,6 +29,7 @@ module Test # :nodoc:
|
|
29
29
|
# ---------------------- internal ---------------------------
|
30
30
|
|
31
31
|
def prepare_request(action, service_name, api_method_name, *args)
|
32
|
+
@request.recycle!
|
32
33
|
@request.request_parameters['action'] = action
|
33
34
|
@request.env['REQUEST_METHOD'] = 'POST'
|
34
35
|
@request.env['HTTP_CONTENT_TYPE'] = 'text/xml'
|
@@ -81,7 +82,7 @@ module Test # :nodoc:
|
|
81
82
|
|
82
83
|
def protocol
|
83
84
|
if @protocol.nil?
|
84
|
-
@protocol ||= ActionWebService::Protocol::Soap::SoapProtocol.
|
85
|
+
@protocol ||= ActionWebService::Protocol::Soap::SoapProtocol.create(@controller)
|
85
86
|
else
|
86
87
|
case @protocol
|
87
88
|
when :xmlrpc
|
data/test/abstract_dispatcher.rb
CHANGED
@@ -4,6 +4,7 @@ require 'stringio'
|
|
4
4
|
class ActionController::Base; def rescue_action(e) raise e end; end
|
5
5
|
|
6
6
|
module DispatcherTest
|
7
|
+
Utf8String = "One World Caf\303\251"
|
7
8
|
WsdlNamespace = 'http://rubyonrails.com/some/namespace'
|
8
9
|
|
9
10
|
class Node < ActiveRecord::Base
|
@@ -58,6 +59,7 @@ module DispatcherTest
|
|
58
59
|
api_method :hash_struct_return, :returns => [[Person]]
|
59
60
|
api_method :thrower
|
60
61
|
api_method :void
|
62
|
+
api_method :test_utf8, :returns => [:string]
|
61
63
|
api_method :hex, :expects => [:base64], :returns => [:string]
|
62
64
|
api_method :unhex, :expects => [:string], :returns => [:base64]
|
63
65
|
end
|
@@ -105,11 +107,15 @@ module DispatcherTest
|
|
105
107
|
class MTAPI < ActionWebService::API::Base
|
106
108
|
inflect_names false
|
107
109
|
api_method :getCategories, :returns => [[:string]]
|
110
|
+
api_method :bool, :returns => [:bool]
|
111
|
+
api_method :alwaysFail
|
108
112
|
end
|
109
113
|
|
110
114
|
class BloggerAPI < ActionWebService::API::Base
|
111
115
|
inflect_names false
|
112
116
|
api_method :getCategories, :returns => [[:string]]
|
117
|
+
api_method :str, :expects => [:int], :returns => [:string]
|
118
|
+
api_method :alwaysFail
|
113
119
|
end
|
114
120
|
|
115
121
|
class MTService < ActionWebService::Base
|
@@ -118,6 +124,14 @@ module DispatcherTest
|
|
118
124
|
def getCategories
|
119
125
|
["mtCat1", "mtCat2"]
|
120
126
|
end
|
127
|
+
|
128
|
+
def bool
|
129
|
+
'y'
|
130
|
+
end
|
131
|
+
|
132
|
+
def alwaysFail
|
133
|
+
raise "MT AlwaysFail"
|
134
|
+
end
|
121
135
|
end
|
122
136
|
|
123
137
|
class BloggerService < ActionWebService::Base
|
@@ -126,6 +140,17 @@ module DispatcherTest
|
|
126
140
|
def getCategories
|
127
141
|
["bloggerCat1", "bloggerCat2"]
|
128
142
|
end
|
143
|
+
|
144
|
+
def str(int)
|
145
|
+
unless int.is_a?(Integer)
|
146
|
+
raise "Not an integer!"
|
147
|
+
end
|
148
|
+
500 + int
|
149
|
+
end
|
150
|
+
|
151
|
+
def alwaysFail
|
152
|
+
raise "Blogger AlwaysFail"
|
153
|
+
end
|
129
154
|
end
|
130
155
|
|
131
156
|
class AbstractController < ActionController::Base
|
@@ -223,6 +248,10 @@ module DispatcherTest
|
|
223
248
|
@void_called = @method_params
|
224
249
|
end
|
225
250
|
|
251
|
+
def test_utf8
|
252
|
+
Utf8String
|
253
|
+
end
|
254
|
+
|
226
255
|
def hex(s)
|
227
256
|
return s.unpack("H*")[0]
|
228
257
|
end
|
@@ -398,12 +427,6 @@ module DispatcherCommonTests
|
|
398
427
|
raise NotImplementedError
|
399
428
|
end
|
400
429
|
|
401
|
-
def update_request(ap_request)
|
402
|
-
end
|
403
|
-
|
404
|
-
def check_response(ap_response)
|
405
|
-
end
|
406
|
-
|
407
430
|
def protocol
|
408
431
|
@protocol
|
409
432
|
end
|
@@ -439,8 +462,8 @@ module DispatcherCommonTests
|
|
439
462
|
public_method_name = real_method_name
|
440
463
|
request_env['HTTP_SOAPACTION'] = "/soap/#{service_name}/#{real_method_name}"
|
441
464
|
end
|
442
|
-
api = container.web_service_object(service_name.to_sym).class.web_service_api
|
443
|
-
method = api.public_api_method_instance(real_method_name)
|
465
|
+
api = container.web_service_object(service_name.to_sym).class.web_service_api rescue nil
|
466
|
+
method = api.public_api_method_instance(real_method_name) rescue nil
|
444
467
|
service_name = self.service_name(container)
|
445
468
|
end
|
446
469
|
protocol.register_api(api)
|
@@ -453,11 +476,10 @@ module DispatcherCommonTests
|
|
453
476
|
# puts body
|
454
477
|
ap_request = protocol.encode_action_pack_request(service_name, public_method_name, body, :request_class => ActionController::TestRequest)
|
455
478
|
ap_request.env.update(request_env)
|
456
|
-
update_request(ap_request)
|
457
479
|
ap_response = ActionController::TestResponse.new
|
458
480
|
container.process(ap_request, ap_response)
|
459
481
|
# puts ap_response.body
|
460
|
-
|
482
|
+
@response_body = ap_response.body
|
461
483
|
public_method_name, return_value = protocol.decode_response(ap_response.body)
|
462
484
|
unless is_exception?(return_value) || virtual
|
463
485
|
return_value = method.cast_returns(return_value)
|
@@ -67,16 +67,25 @@ class TC_DispatcherActionControllerSoap < Test::Unit::TestCase
|
|
67
67
|
assert_equal(["bloggerCat1", "bloggerCat2"], blogger_cats)
|
68
68
|
end
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
70
|
+
def test_utf8
|
71
|
+
@direct_controller.web_service_exception_reporting = true
|
72
|
+
$KCODE = 'u'
|
73
|
+
assert_equal(Utf8String, do_method_call(@direct_controller, 'TestUtf8'))
|
74
|
+
retval = SOAP::Processor.unmarshal(@response_body).body.response
|
75
|
+
assert retval.is_a?(SOAP::SOAPString)
|
76
|
+
|
77
|
+
# If $KCODE is not set to UTF-8, any strings with non-ASCII UTF-8 data
|
78
|
+
# will be sent back as base64 by SOAP4R. By the time we get it here though,
|
79
|
+
# it will be decoded back into a string. So lets read the base64 value
|
80
|
+
# from the message body directly.
|
81
|
+
$KCODE = 'NONE'
|
82
|
+
do_method_call(@direct_controller, 'TestUtf8')
|
83
|
+
retval = SOAP::Processor.unmarshal(@response_body).body.response
|
84
|
+
assert retval.is_a?(SOAP::SOAPBase64)
|
85
|
+
assert_equal "T25lIFdvcmxkIENhZsOp", retval.data.to_s
|
86
|
+
end
|
79
87
|
|
88
|
+
protected
|
80
89
|
def exception_message(soap_fault_exception)
|
81
90
|
soap_fault_exception.detail.cause.message
|
82
91
|
end
|
@@ -19,6 +19,29 @@ class TC_DispatcherActionControllerXmlRpc < Test::Unit::TestCase
|
|
19
19
|
assert_equal(["bloggerCat1", "bloggerCat2"], blogger_cats)
|
20
20
|
end
|
21
21
|
|
22
|
+
def test_multicall
|
23
|
+
response = do_method_call(@layered_controller, 'system.multicall', [
|
24
|
+
{'methodName' => 'mt.getCategories'},
|
25
|
+
{'methodName' => 'blogger.getCategories'},
|
26
|
+
{'methodName' => 'mt.bool'},
|
27
|
+
{'methodName' => 'blogger.str', 'params' => ['2000']},
|
28
|
+
{'methodName' => 'mt.alwaysFail'},
|
29
|
+
{'methodName' => 'blogger.alwaysFail'},
|
30
|
+
{'methodName' => 'mt.blah'},
|
31
|
+
{'methodName' => 'blah.blah'}
|
32
|
+
])
|
33
|
+
assert_equal [
|
34
|
+
[["mtCat1", "mtCat2"]],
|
35
|
+
[["bloggerCat1", "bloggerCat2"]],
|
36
|
+
[true],
|
37
|
+
["2500"],
|
38
|
+
{"faultCode" => 3, "faultString" => "MT AlwaysFail"},
|
39
|
+
{"faultCode" => 3, "faultString" => "Blogger AlwaysFail"},
|
40
|
+
{"faultCode" => 4, "faultMessage" => "no such method 'blah' on API DispatcherTest::MTAPI"},
|
41
|
+
{"faultCode" => 4, "faultMessage" => "no such web service 'blah'"}
|
42
|
+
], response
|
43
|
+
end
|
44
|
+
|
22
45
|
protected
|
23
46
|
def exception_message(xmlrpc_fault_exception)
|
24
47
|
xmlrpc_fault_exception.faultString
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.10
|
|
3
3
|
specification_version: 1
|
4
4
|
name: actionwebservice
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2005-
|
6
|
+
version: 0.9.1
|
7
|
+
date: 2005-10-19
|
8
8
|
summary: Web service support for Action Pack.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -72,6 +72,7 @@ files:
|
|
72
72
|
- lib/action_web_service/support
|
73
73
|
- lib/action_web_service/templates
|
74
74
|
- lib/action_web_service/test_invoke.rb
|
75
|
+
- lib/action_web_service/version.rb
|
75
76
|
- lib/action_web_service/client/base.rb
|
76
77
|
- lib/action_web_service/client/soap_client.rb
|
77
78
|
- lib/action_web_service/client/xmlrpc_client.rb
|
@@ -129,7 +130,7 @@ dependencies:
|
|
129
130
|
-
|
130
131
|
- "="
|
131
132
|
- !ruby/object:Gem::Version
|
132
|
-
version: 1.
|
133
|
+
version: 1.10.1
|
133
134
|
version:
|
134
135
|
- !ruby/object:Gem::Dependency
|
135
136
|
name: activerecord
|
@@ -139,7 +140,7 @@ dependencies:
|
|
139
140
|
-
|
140
141
|
- "="
|
141
142
|
- !ruby/object:Gem::Version
|
142
|
-
version: 1.
|
143
|
+
version: 1.12.1
|
143
144
|
version:
|
144
145
|
- !ruby/object:Gem::Dependency
|
145
146
|
name: activesupport
|
@@ -149,5 +150,5 @@ dependencies:
|
|
149
150
|
-
|
150
151
|
- "="
|
151
152
|
- !ruby/object:Gem::Version
|
152
|
-
version: 1.
|
153
|
+
version: 1.2.1
|
153
154
|
version:
|