aboutsummaryrefslogtreecommitdiffstats
path: root/actionwebservice/lib/action_web_service/dispatcher
diff options
context:
space:
mode:
authorLeon Breedt <bitserf@gmail.com>2005-04-02 21:03:36 +0000
committerLeon Breedt <bitserf@gmail.com>2005-04-02 21:03:36 +0000
commitaaea48fe9826b9e5d2d5b92795a297b8f238c58d (patch)
treee7c01c7f95d467f837c1f96d58dac74c3c902610 /actionwebservice/lib/action_web_service/dispatcher
parentaa09c770e9b5400683be11952673017295246de7 (diff)
downloadrails-aaea48fe9826b9e5d2d5b92795a297b8f238c58d.tar.gz
rails-aaea48fe9826b9e5d2d5b92795a297b8f238c58d.tar.bz2
rails-aaea48fe9826b9e5d2d5b92795a297b8f238c58d.zip
* collapse 'ws' back into protocols, it just added complexity and indirection, and was hard to extend.
* extract casting into seperate support file * ensure casting always does the right thing for return values, should fix interoperability issues with Ecto and possibly other XML-RPC clients * add functional unit tests for scaffolding * represent signature items with classes instead of symbols/Class objects, much more flexible * tweak logging to always show casted versions of parameters and return values, if possible. git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1072 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionwebservice/lib/action_web_service/dispatcher')
-rw-r--r--actionwebservice/lib/action_web_service/dispatcher/abstract.rb40
-rw-r--r--actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb63
2 files changed, 53 insertions, 50 deletions
diff --git a/actionwebservice/lib/action_web_service/dispatcher/abstract.rb b/actionwebservice/lib/action_web_service/dispatcher/abstract.rb
index 69c3b9de3b..975120212f 100644
--- a/actionwebservice/lib/action_web_service/dispatcher/abstract.rb
+++ b/actionwebservice/lib/action_web_service/dispatcher/abstract.rb
@@ -12,14 +12,6 @@ module ActionWebService # :nodoc:
base.send(:include, ActionWebService::Dispatcher::InstanceMethods)
end
- def self.layered_service_name(public_method_name) # :nodoc:
- if public_method_name =~ /^([^\.]+)\.(.*)$/
- $1
- else
- nil
- end
- end
-
module InstanceMethods # :nodoc:
private
def invoke_web_service_request(protocol_request)
@@ -40,13 +32,7 @@ module ActionWebService # :nodoc:
else
return_value = self.__send__(invocation.api_method.name)
end
- if invocation.api.has_api_method?(invocation.api_method.name)
- api_method = invocation.api_method
- else
- api_method = invocation.api_method.dup
- api_method.instance_eval{ @returns = [ return_value.class ] }
- end
- invocation.protocol.marshal_response(api_method, return_value)
+ web_service_create_response(invocation.protocol, invocation.api, invocation.api_method, return_value)
end
def web_service_delegated_invoke(invocation)
@@ -57,7 +43,7 @@ module ActionWebService # :nodoc:
if cancellation_reason
raise(DispatcherError, "request canceled: #{cancellation_reason}")
end
- invocation.protocol.marshal_response(invocation.api_method, return_value)
+ web_service_create_response(invocation.protocol, invocation.api, invocation.api_method, return_value)
end
def web_service_invocation(request)
@@ -79,6 +65,7 @@ module ActionWebService # :nodoc:
invocation.service = web_service_object(invocation.service_name)
invocation.api = invocation.service.class.web_service_api
end
+ invocation.protocol.register_api(invocation.api)
request.api = invocation.api
if invocation.api.has_public_api_method?(public_method_name)
invocation.api_method = invocation.api.public_api_method_instance(public_method_name)
@@ -89,15 +76,20 @@ module ActionWebService # :nodoc:
invocation.api_method = invocation.api.default_api_method_instance
end
end
+ if invocation.service.nil?
+ raise(DispatcherError, "no service available for service name #{invocation.service_name}")
+ end
unless invocation.service.respond_to?(invocation.api_method.name)
- raise(DispatcherError, "no such method '#{public_method_name}' on API #{invocation.api} (#{invocation.api_method.name})")
+ raise(DispatcherError, "no such method '#{public_method_name}' on API #{invocation.api} (#{invocation.api_method.name})")
end
request.api_method = invocation.api_method
begin
- invocation.method_ordered_params = invocation.api_method.cast_expects_ws2ruby(request.protocol.marshaler, request.method_params)
+ invocation.method_ordered_params = invocation.api_method.cast_expects(request.method_params.dup)
rescue
- invocation.method_ordered_params = request.method_params.map{ |x| x.value }
+ logger.warn "Casting of method parameters failed" unless logger.nil?
+ invocation.method_ordered_params = request.method_params
end
+ request.method_params = invocation.method_ordered_params
invocation.method_named_params = {}
invocation.api_method.param_names.inject(0) do |m, n|
invocation.method_named_params[n] = invocation.method_ordered_params[m]
@@ -106,6 +98,16 @@ module ActionWebService # :nodoc:
invocation
end
+ def web_service_create_response(protocol, api, api_method, return_value)
+ if api.has_api_method?(api_method.name)
+ return_type = api_method.returns ? api_method.returns[0] : nil
+ return_value = api_method.cast_returns(return_value)
+ else
+ return_type = ActionWebService::SignatureTypes.canonical_signature_entry(return_value.class, 0)
+ end
+ protocol.encode_response(api_method.public_name + 'Response', return_value, return_type)
+ end
+
class Invocation # :nodoc:
attr_accessor :protocol
attr_accessor :service_name
diff --git a/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb b/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb
index 0140039c49..a4659e5183 100644
--- a/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb
+++ b/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb
@@ -45,7 +45,6 @@ module ActionWebService # :nodoc:
exception = e
end
if request
- log_request(request, @request.raw_post)
response = nil
exception = nil
bm = Benchmark.measure do
@@ -55,6 +54,7 @@ module ActionWebService # :nodoc:
exception = e
end
end
+ log_request(request, @request.raw_post)
if exception
log_error(exception) unless logger.nil?
send_web_service_error_response(request, exception)
@@ -82,10 +82,10 @@ module ActionWebService # :nodoc:
unless self.class.web_service_exception_reporting
exception = DispatcherError.new("Internal server error (exception raised)")
end
- api_method = request.api_method ? request.api_method.dup : nil
- api_method ||= request.api.dummy_api_method_instance(request.method_name)
- api_method.instance_eval{ @returns = [ exception.class ] }
- response = request.protocol.marshal_response(api_method, exception)
+ api_method = request.api_method
+ public_method_name = api_method ? api_method.public_name : request.method_name
+ return_type = ActionWebService::SignatureTypes.canonical_signature_entry(Exception, 0)
+ response = request.protocol.encode_response(public_method_name + 'Response', exception, return_type)
send_web_service_response(response)
else
if self.class.web_service_exception_reporting
@@ -118,7 +118,14 @@ module ActionWebService # :nodoc:
def log_request(request, body)
unless logger.nil?
name = request.method_name
- params = request.method_params.map{|x| "#{x.info.name}=>#{x.value.inspect}"}
+ api_method = request.api_method
+ params = request.method_params
+ if api_method && api_method.expects
+ i = 0
+ params = api_method.expects.map{ |type| param = "#{type.name}=>#{params[i].inspect}"; i+= 1; param }
+ else
+ params = params.map{ |param| param.inspect }
+ end
service = request.service_name
logger.debug("\nWeb Service Request: #{name}(#{params.join(", ")}) Entrypoint: #{service}")
logger.debug(indent(body))
@@ -127,7 +134,8 @@ module ActionWebService # :nodoc:
def log_response(response, elapsed=nil)
unless logger.nil?
- logger.debug("\nWeb Service Response" + (elapsed ? " (%f):" % elapsed : ":"))
+ elapsed = (elapsed ? " (%f):" % elapsed : ":")
+ logger.debug("\nWeb Service Response" + elapsed + " => #{response.return_value.inspect}")
logger.debug(indent(response.body))
end
end
@@ -171,7 +179,7 @@ module ActionWebService # :nodoc:
namespace = 'urn:ActionWebService'
soap_action_base = "/#{controller_name}"
- marshaler = WS::Marshaling::SoapMarshaler.new(namespace)
+ marshaler = ActionWebService::Protocol::Soap::SoapMarshaler.new(namespace)
apis = {}
case dispatching_mode
when :direct
@@ -208,7 +216,7 @@ module ActionWebService # :nodoc:
xm.xsd(:schema, 'xmlns' => XsdNs, 'targetNamespace' => namespace) do
custom_types.each do |binding|
case
- when binding.is_typed_array?
+ when binding.type.array?
xm.xsd(:complexType, 'name' => binding.type_name) do
xm.xsd(:complexContent) do
xm.xsd(:restriction, 'base' => 'soapenc:Array') do
@@ -217,11 +225,11 @@ module ActionWebService # :nodoc:
end
end
end
- when binding.is_typed_struct?
+ when binding.type.structured?
xm.xsd(:complexType, 'name' => binding.type_name) do
xm.xsd(:all) do
- binding.each_member do |name, spec|
- b = marshaler.register_type(spec)
+ binding.type.each_member do |name, type|
+ b = marshaler.register_type(type)
xm.xsd(:element, 'name' => name, 'type' => b.qualified_type_name('typens'))
end
end
@@ -249,14 +257,8 @@ module ActionWebService # :nodoc:
expects = method.expects
i = 1
expects.each do |type|
- if type.is_a?(Hash)
- param_name = type.keys.shift
- type = type.values.shift
- else
- param_name = "param#{i}"
- end
binding = marshaler.register_type(type)
- xm.part('name' => param_name, 'type' => binding.qualified_type_name('typens'))
+ xm.part('name' => type.name, 'type' => binding.qualified_type_name('typens'))
i += 1
end if expects
end
@@ -340,7 +342,9 @@ module ActionWebService # :nodoc:
def register_api(api, marshaler)
bindings = {}
traverse_custom_types(api, marshaler) do |binding|
- bindings[binding] = nil unless bindings.has_key?(binding.type_class)
+ bindings[binding] = nil unless bindings.has_key?(binding)
+ element_binding = binding.element_binding
+ bindings[binding.element_binding] = nil if element_binding && !bindings.has_key?(element_binding)
end
bindings.keys
end
@@ -348,21 +352,18 @@ module ActionWebService # :nodoc:
def traverse_custom_types(api, marshaler, &block)
api.api_methods.each do |name, method|
expects, returns = method.expects, method.returns
- expects.each{|x| traverse_custom_type_spec(marshaler, x, &block)} if expects
- returns.each{|x| traverse_custom_type_spec(marshaler, x, &block)} if returns
+ expects.each{ |type| traverse_type(marshaler, type, &block) if type.custom? } if expects
+ returns.each{ |type| traverse_type(marshaler, type, &block) if type.custom? } if returns
end
end
- def traverse_custom_type_spec(marshaler, spec, &block)
- binding = marshaler.register_type(spec)
- if binding.is_typed_struct?
- binding.each_member do |name, member_spec|
- traverse_custom_type_spec(marshaler, member_spec, &block)
- end
- elsif binding.is_typed_array?
- traverse_custom_type_spec(marshaler, binding.element_binding.type_class, &block)
+ def traverse_type(marshaler, type, &block)
+ yield marshaler.register_type(type)
+ if type.array?
+ yield marshaler.register_type(type.element_type)
+ type = type.element_type
end
- yield binding
+ type.each_member{ |name, type| traverse_type(marshaler, type, &block) } if type.structured?
end
end
end