actionwebservice 0.8.1 → 0.9.1
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 +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:
|