aboutsummaryrefslogtreecommitdiffstats
path: root/actionwebservice
diff options
context:
space:
mode:
authorLeon Breedt <bitserf@gmail.com>2005-02-19 08:29:42 +0000
committerLeon Breedt <bitserf@gmail.com>2005-02-19 08:29:42 +0000
commit418d487020d24e69b528fdbedfecb20a87f99fcb (patch)
tree1956d6982123df1638bdef8274dff50ae71b25c2 /actionwebservice
parente7499638d06023ae493d14ec1dc4f58bad8ac168 (diff)
downloadrails-418d487020d24e69b528fdbedfecb20a87f99fcb.tar.gz
rails-418d487020d24e69b528fdbedfecb20a87f99fcb.tar.bz2
rails-418d487020d24e69b528fdbedfecb20a87f99fcb.zip
refactoring:
* move dispatching out of the Container into Dispatcher, it makes more sense for Container to only contain the list of web services defined in it. * collapse Wsdl and ActionController "routers" into an ActionController-specific module, no advantage to having them seperate as they were quite tightly coupled. rename to Dispatcher, to avoi confusion with Routing. * add a "_thing" suffix to concept-specific filenames. this is so that we don't end up with many soap.rb files, for example. * remove "virtual invocation" support. adds complexity, and it doesn't seem to add any value. git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@679 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionwebservice')
-rw-r--r--actionwebservice/ChangeLog9
-rw-r--r--actionwebservice/HACKING44
-rw-r--r--actionwebservice/Rakefile4
-rw-r--r--actionwebservice/TODO13
-rw-r--r--actionwebservice/lib/action_web_service.rb6
-rw-r--r--actionwebservice/lib/action_web_service/client.rb4
-rw-r--r--actionwebservice/lib/action_web_service/client/soap_client.rb (renamed from actionwebservice/lib/action_web_service/client/soap.rb)0
-rw-r--r--actionwebservice/lib/action_web_service/client/xmlrpc_client.rb (renamed from actionwebservice/lib/action_web_service/client/xmlrpc.rb)0
-rw-r--r--actionwebservice/lib/action_web_service/container.rb147
-rw-r--r--actionwebservice/lib/action_web_service/dispatcher.rb2
-rw-r--r--actionwebservice/lib/action_web_service/dispatcher/abstract.rb158
-rw-r--r--actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb (renamed from actionwebservice/lib/action_web_service/router/wsdl.rb)109
-rw-r--r--actionwebservice/lib/action_web_service/invocation.rb61
-rw-r--r--actionwebservice/lib/action_web_service/protocol.rb4
-rw-r--r--actionwebservice/lib/action_web_service/protocol/soap_protocol.rb (renamed from actionwebservice/lib/action_web_service/protocol/soap.rb)0
-rw-r--r--actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb (renamed from actionwebservice/lib/action_web_service/protocol/xmlrpc.rb)15
-rw-r--r--actionwebservice/lib/action_web_service/router.rb2
-rw-r--r--actionwebservice/lib/action_web_service/router/action_controller.rb99
-rw-r--r--actionwebservice/test/abstract_client.rb2
-rw-r--r--actionwebservice/test/dispatcher_action_controller_test.rb (renamed from actionwebservice/test/router_action_controller_test.rb)89
-rw-r--r--actionwebservice/test/invocation_test.rb13
-rw-r--r--actionwebservice/test/protocol_soap_test.rb60
-rw-r--r--actionwebservice/test/protocol_xmlrpc_test.rb14
-rw-r--r--actionwebservice/test/router_wsdl_test.rb100
24 files changed, 404 insertions, 551 deletions
diff --git a/actionwebservice/ChangeLog b/actionwebservice/ChangeLog
index c9803bd2b7..4efc01f46a 100644
--- a/actionwebservice/ChangeLog
+++ b/actionwebservice/ChangeLog
@@ -1,8 +1,11 @@
UNRELEASED
- * lib/*,test/*,examples/*: prefix all generic "service"
- type names with web_. update all using code as well as
- the RDoc.
+ * lib/action_service/dispatcher*: replaces "router" fragments with
+ one file for Action Controllers, moves dispatching work out of
+ the container
+ * lib/*,test/*,examples/*: rename project to
+ ActionWebService. prefix all generic "service" type names with web_.
+ update all using code as well as the RDoc.
* lib/action_service/router/wsdl.rb: ensure that #wsdl is
defined in the final container class, or the new ActionPack
filtering will exclude it
diff --git a/actionwebservice/HACKING b/actionwebservice/HACKING
deleted file mode 100644
index 536aac7a24..0000000000
--- a/actionwebservice/HACKING
+++ /dev/null
@@ -1,44 +0,0 @@
-== Coding Style
-
-Please try to follow Rails conventions and idioms.
-
-
-== Concepts
-
- * Service
- A service has an associated API definition, and
- implements the methods defined in the API definition
-
- * Container
- A container contains zero or more services
-
- * API
- An API definition defines a list of methods implemented by
- a service
-
- * Router
- A router takes raw wire requests, decodes them, performs the invocation on
- the service, and generates raw wire responses from the invocation result.
- A router is mixed into a container class.
-
- * Protocol
- A protocol implementation implements the unmarshaling and marshaling of
- raw wire requests and responses. Registers with router.
-
-
-== Action Pack Integration
-
-For Action Pack, the ActionController is both container and router, and also contains
-the protocol implementations.
-
-
-== Adding support for a new protocol
-
- 1. Add an ActionWebService::Protocol::YourProtocol module and any classes you need to
- perform unmarshaling/marshaling of protocol requests. See the SOAP implementation
- for an example of a complex mapping, and also see
- ActionWebService::Protocol::AbstractProtocol for the methods you need to implement.
-
- 2. Add unit tests for your new protocol. Be sure to test using a Action Pack test request
- duplicating how the real requests will arrive and verify that mapping to and from Ruby
- types works correctly.
diff --git a/actionwebservice/Rakefile b/actionwebservice/Rakefile
index 49c3409e60..3e57e48d88 100644
--- a/actionwebservice/Rakefile
+++ b/actionwebservice/Rakefile
@@ -36,7 +36,7 @@ Rake::RDocTask.new { |rdoc|
rdoc.rdoc_files.include('lib/action_web_service/api/*.rb')
rdoc.rdoc_files.include('lib/action_web_service/client/*.rb')
rdoc.rdoc_files.include('lib/action_web_service/protocol/*.rb')
- rdoc.rdoc_files.include('lib/action_web_service/router/*.rb')
+ rdoc.rdoc_files.include('lib/action_web_service/dispatcher/*.rb')
rdoc.rdoc_files.include('lib/action_web_service/support/*.rb')
}
@@ -63,7 +63,7 @@ spec = Gem::Specification.new do |s|
s.require_path = 'lib'
s.autorequire = 'action_web_service'
- s.files = [ "Rakefile", "setup.rb", "README", "TODO", "HACKING", "ChangeLog", "MIT-LICENSE" ]
+ s.files = [ "Rakefile", "setup.rb", "README", "TODO", "ChangeLog", "MIT-LICENSE" ]
s.files = s.files + Dir.glob( "examples/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
s.files = s.files + Dir.glob( "lib/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
s.files = s.files + Dir.glob( "test/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
diff --git a/actionwebservice/TODO b/actionwebservice/TODO
index e753fbb1d7..35c6c66f11 100644
--- a/actionwebservice/TODO
+++ b/actionwebservice/TODO
@@ -1,8 +1,11 @@
= 0.4.0 Tasks
- add ActiveRecord-like logging that includes timing information
- - rename project to 'actionwebservice', Action Web Service
= Post-0.4.0 Tasks
+ - support namespaced custom types in WSDL in a way that interoperates
+ with .NET (.NET croaks on '::' currently). perhaps a transform
+ that maps Ruby::Class to Ruby.Class and back.
+
- relax type-checking for XML-RPC, and perform casts between base types if there
are mismatches (i.e. String received when Integer expected, or vice-versa)
@@ -23,12 +26,8 @@
web_service :xmlrpc { BloggingServices.new(@request) }
end
- - supported namespaced custom types in WSDL in a way that interoperates
- with .NET (.NET croaks on '::' currently)
-
- - simplification: collapse Router::ActionController, Router::Wsdl
- and API::ActionController into Container::ActionController.
- the seperation has gained us nothing.
+ - verify that cookie support works, and add cookie-authenticated
+ service examples. test with .NET.
= Low priority tasks
- add better type mapping tests for XML-RPC
diff --git a/actionwebservice/lib/action_web_service.rb b/actionwebservice/lib/action_web_service.rb
index a55afc2244..5cf988a0f8 100644
--- a/actionwebservice/lib/action_web_service.rb
+++ b/actionwebservice/lib/action_web_service.rb
@@ -41,7 +41,7 @@ require 'action_web_service/api'
require 'action_web_service/struct'
require 'action_web_service/container'
require 'action_web_service/protocol'
-require 'action_web_service/router'
+require 'action_web_service/dispatcher'
ActionWebService::Base.class_eval do
include ActionWebService::API
@@ -55,6 +55,6 @@ ActionController::Base.class_eval do
include ActionWebService::Protocol::XmlRpc
include ActionWebService::API
include ActionWebService::API::ActionController
- include ActionWebService::Router::ActionController
- include ActionWebService::Router::Wsdl
+ include ActionWebService::Dispatcher
+ include ActionWebService::Dispatcher::ActionController
end
diff --git a/actionwebservice/lib/action_web_service/client.rb b/actionwebservice/lib/action_web_service/client.rb
index 77f934882c..2a1e33054d 100644
--- a/actionwebservice/lib/action_web_service/client.rb
+++ b/actionwebservice/lib/action_web_service/client.rb
@@ -1,3 +1,3 @@
require 'action_web_service/client/base'
-require 'action_web_service/client/soap'
-require 'action_web_service/client/xmlrpc'
+require 'action_web_service/client/soap_client'
+require 'action_web_service/client/xmlrpc_client'
diff --git a/actionwebservice/lib/action_web_service/client/soap.rb b/actionwebservice/lib/action_web_service/client/soap_client.rb
index 3557f88594..3557f88594 100644
--- a/actionwebservice/lib/action_web_service/client/soap.rb
+++ b/actionwebservice/lib/action_web_service/client/soap_client.rb
diff --git a/actionwebservice/lib/action_web_service/client/xmlrpc.rb b/actionwebservice/lib/action_web_service/client/xmlrpc_client.rb
index df51230b81..df51230b81 100644
--- a/actionwebservice/lib/action_web_service/client/xmlrpc.rb
+++ b/actionwebservice/lib/action_web_service/client/xmlrpc_client.rb
diff --git a/actionwebservice/lib/action_web_service/container.rb b/actionwebservice/lib/action_web_service/container.rb
index 6fa14def56..f02717579e 100644
--- a/actionwebservice/lib/action_web_service/container.rb
+++ b/actionwebservice/lib/action_web_service/container.rb
@@ -5,8 +5,6 @@ module ActionWebService # :nodoc:
def self.append_features(base) # :nodoc:
super
- base.class_inheritable_option(:web_service_dispatching_mode, :direct)
- base.class_inheritable_option(:web_service_exception_reporting, true)
base.extend(ClassMethods)
base.send(:include, ActionWebService::Container::InstanceMethods)
end
@@ -82,151 +80,6 @@ module ActionWebService # :nodoc:
service = info[:block]
service ? instance_eval(&service) : info[:object]
end
-
- private
- def dispatch_web_service_request(protocol_request)
- case web_service_dispatching_mode
- when :direct
- dispatch_direct_web_service_request(protocol_request)
- when :delegated
- dispatch_delegated_web_service_request(protocol_request)
- else
- raise(ContainerError, "unsupported dispatching mode :#{web_service_dispatching_mode}")
- end
- end
-
- def dispatch_direct_web_service_request(protocol_request)
- public_method_name = protocol_request.public_method_name
- api = self.class.web_service_api
- method_name = api.api_method_name(public_method_name)
- block = nil
- expects = nil
- if method_name
- signature = api.api_methods[method_name]
- expects = signature[:expects]
- protocol_request.type = Protocol::CheckedMessage
- protocol_request.signature = expects
- protocol_request.return_signature = signature[:returns]
- else
- protocol_request.type = Protocol::UncheckedMessage
- system_methods = self.class.read_inheritable_attribute('default_system_methods') || {}
- protocol = protocol_request.protocol
- block = system_methods[protocol.class]
- unless block
- method_name = api.default_api_method
- unless method_name && respond_to?(method_name)
- raise(ContainerError, "no such method ##{public_method_name}")
- end
- end
- end
-
- @method_params = protocol_request.unmarshal
- @params ||= {}
- if expects
- (1..@method_params.size).each do |i|
- i -= 1
- if expects[i].is_a?(Hash)
- @params[expects[i].keys.shift.to_s] = @method_params[i]
- else
- @params["param#{i}"] = @method_params[i]
- end
- end
- end
-
- if respond_to?(:before_action)
- @params['action'] = method_name.to_s
- return protocol_request.marshal(nil) if before_action == false
- end
-
- perform_invoke = lambda do
- if block
- block.call(public_method_name, self.class, *@method_params)
- else
- send(method_name)
- end
- end
- try_default = true
- result = nil
- catch(:try_default) do
- result = perform_invoke.call
- try_default = false
- end
- if try_default
- method_name = api.default_api_method
- if method_name
- protocol_request.type = Protocol::UncheckedMessage
- else
- raise(ContainerError, "no such method ##{public_method_name}")
- end
- result = perform_invoke.call
- end
- after_action if respond_to?(:after_action)
- protocol_request.marshal(result)
- end
-
- def dispatch_delegated_web_service_request(protocol_request)
- web_service_name = protocol_request.web_service_name
- service = web_service_object(web_service_name)
- api = service.class.web_service_api
- public_method_name = protocol_request.public_method_name
- method_name = api.api_method_name(public_method_name)
-
- invocation = ActionWebService::Invocation::InvocationRequest.new(
- ActionWebService::Invocation::ConcreteInvocation,
- public_method_name,
- method_name)
-
- if method_name
- protocol_request.type = Protocol::CheckedMessage
- signature = api.api_methods[method_name]
- protocol_request.signature = signature[:expects]
- protocol_request.return_signature = signature[:returns]
- invocation.params = protocol_request.unmarshal
- else
- protocol_request.type = Protocol::UncheckedMessage
- invocation.type = ActionWebService::Invocation::VirtualInvocation
- system_methods = self.class.read_inheritable_attribute('default_system_methods') || {}
- protocol = protocol_request.protocol
- block = system_methods[protocol.class]
- if block
- invocation.block = block
- invocation.block_params << service.class
- else
- method_name = api.default_api_method
- if method_name && service.respond_to?(method_name)
- invocation.params = protocol_request.unmarshal
- invocation.method_name = method_name.to_sym
- else
- raise(ContainerError, "no such method /#{web_service_name}##{public_method_name}")
- end
- end
- end
-
- canceled_reason = nil
- canceled_block = lambda{|r| canceled_reason = r}
- perform_invoke = lambda do
- service.perform_invocation(invocation, &canceled_block)
- end
- try_default = true
- result = nil
- catch(:try_default) do
- result = perform_invoke.call
- try_default = false
- end
- if try_default
- method_name = api.default_api_method
- if method_name
- protocol_request.type = Protocol::UncheckedMessage
- invocation.params = protocol_request.unmarshal
- invocation.method_name = method_name.to_sym
- invocation.type = ActionWebService::Invocation::UnpublishedConcreteInvocation
- else
- raise(ContainerError, "no such method /#{web_service_name}##{public_method_name}")
- end
- result = perform_invoke.call
- end
- protocol_request.marshal(result)
- end
end
end
end
diff --git a/actionwebservice/lib/action_web_service/dispatcher.rb b/actionwebservice/lib/action_web_service/dispatcher.rb
new file mode 100644
index 0000000000..601d831373
--- /dev/null
+++ b/actionwebservice/lib/action_web_service/dispatcher.rb
@@ -0,0 +1,2 @@
+require 'action_web_service/dispatcher/abstract'
+require 'action_web_service/dispatcher/action_controller_dispatcher'
diff --git a/actionwebservice/lib/action_web_service/dispatcher/abstract.rb b/actionwebservice/lib/action_web_service/dispatcher/abstract.rb
new file mode 100644
index 0000000000..e03446924a
--- /dev/null
+++ b/actionwebservice/lib/action_web_service/dispatcher/abstract.rb
@@ -0,0 +1,158 @@
+require 'benchmark'
+
+module ActionWebService # :nodoc:
+ module Dispatcher # :nodoc:
+ class DispatcherError < ActionWebService::ActionWebServiceError # :nodoc:
+ end
+
+ def self.append_features(base) # :nodoc:
+ super
+ base.class_inheritable_option(:web_service_dispatching_mode, :direct)
+ base.class_inheritable_option(:web_service_exception_reporting, true)
+ base.send(:include, ActionWebService::Dispatcher::InstanceMethods)
+ end
+
+ module InstanceMethods # :nodoc:
+ private
+ def dispatch_web_service_request(action_pack_request)
+ protocol_request = protocol_response = nil
+ bm = Benchmark.measure do
+ protocol_request = probe_request_protocol(action_pack_request)
+ protocol_response = dispatch_protocol_request(protocol_request)
+ end
+ [protocol_request, protocol_response, bm.real, nil]
+ rescue Exception => e
+ protocol_response = prepare_exception_response(protocol_request, e)
+ [protocol_request, prepare_exception_response(protocol_request, e), nil, e]
+ end
+
+ def dispatch_protocol_request(protocol_request)
+ case web_service_dispatching_mode
+ when :direct
+ dispatch_direct_request(protocol_request)
+ when :delegated
+ dispatch_delegated_request(protocol_request)
+ else
+ raise(ContainerError, "unsupported dispatching mode :#{web_service_dispatching_mode}")
+ end
+ end
+
+ def dispatch_direct_request(protocol_request)
+ request = prepare_dispatch_request(protocol_request)
+ return_value = direct_invoke(request)
+ protocol_request.marshal(return_value)
+ end
+
+ def dispatch_delegated_request(protocol_request)
+ request = prepare_dispatch_request(protocol_request)
+ return_value = delegated_invoke(request)
+ protocol_request.marshal(return_value)
+ end
+
+ def direct_invoke(request)
+ return nil unless before_direct_invoke(request)
+ return_value = send(request.method_name)
+ after_direct_invoke(request)
+ return_value
+ end
+
+ def before_direct_invoke(request)
+ @method_params = request.params
+ end
+
+ def after_direct_invoke(request)
+ end
+
+ def delegated_invoke(request)
+ cancellation_reason = nil
+ web_service = request.web_service
+ return_value = web_service.perform_invocation(request.method_name, request.params) do |x|
+ cancellation_reason = x
+ end
+ if cancellation_reason
+ raise(DispatcherError, "request canceled: #{cancellation_reason}")
+ end
+ return_value
+ end
+
+ def fallback_invoke(dispatch_request)
+ raise NotImplementedError
+ end
+
+ def prepare_dispatch_request(protocol_request)
+ api = method_name = web_service_name = web_service = params = nil
+ public_method_name = protocol_request.public_method_name
+ case web_service_dispatching_mode
+ when :direct
+ api = self.class.web_service_api
+ when :delegated
+ web_service_name = protocol_request.web_service_name
+ web_service = web_service_object(web_service_name)
+ api = web_service.class.web_service_api
+ end
+ method_name = api.api_method_name(public_method_name)
+ signature = nil
+ if method_name
+ signature = api.api_methods[method_name]
+ protocol_request.type = Protocol::CheckedMessage
+ protocol_request.signature = signature[:expects]
+ protocol_request.return_signature = signature[:returns]
+ else
+ method_name = api.default_api_method
+ if method_name
+ protocol_request.type = Protocol::UncheckedMessage
+ else
+ raise(DispatcherError, "no such method #{web_service_name}##{public_method_name}")
+ end
+ end
+ params = protocol_request.unmarshal
+ DispatchRequest.new(
+ :api => api,
+ :public_method_name => public_method_name,
+ :method_name => method_name,
+ :signature => signature,
+ :web_service_name => web_service_name,
+ :web_service => web_service,
+ :params => params)
+ end
+
+ def prepare_exception_response(protocol_request, exception)
+ if protocol_request && exception
+ case web_service_dispatching_mode
+ when :direct
+ if web_service_exception_reporting
+ return protocol_request.protocol.marshal_exception(exception)
+ else
+ raise exception
+ end
+ when :delegated
+ web_service = web_service_object(protocol_request.web_service_name)
+ if web_service && web_service.class.web_service_exception_reporting
+ return protocol_request.protocol.marshal_exception(exception)
+ else
+ raise exception
+ end
+ end
+ else
+ protocol_request.protocol.marshal_exception(RuntimeError.new("missing protocol request or exception"))
+ end
+ rescue Exception
+ nil
+ end
+
+ class DispatchRequest
+ attr :api
+ attr :public_method_name
+ attr :method_name
+ attr :signature
+ attr :web_service_name
+ attr :web_service
+ attr :params
+
+ def initialize(values={})
+ values.each{|k,v| instance_variable_set("@#{k.to_s}", v)}
+ end
+ end
+ end
+ end
+end
diff --git a/actionwebservice/lib/action_web_service/router/wsdl.rb b/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb
index 6963334818..68c0f4ffb3 100644
--- a/actionwebservice/lib/action_web_service/router/wsdl.rb
+++ b/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb
@@ -1,23 +1,114 @@
module ActionWebService # :nodoc:
- module Router # :nodoc:
- module Wsdl # :nodoc:
+ module Dispatcher # :nodoc:
+ module ActionController # :nodoc:
def self.append_features(base) # :nodoc:
- base.class_eval do
+ super
+ base.class_eval do
class << self
- alias_method :inherited_without_wsdl, :inherited
+ alias_method :inherited_without_action_controller, :inherited
+ end
+ end
+ base.class_eval do
+ alias_method :before_direct_invoke_without_action_controller, :before_direct_invoke
+ alias_method :after_direct_invoke_without_action_controller, :after_direct_invoke
+ end
+ base.add_web_service_api_callback do |klass, api|
+ if klass.web_service_dispatching_mode == :direct
+ klass.class_eval <<-EOS
+ def api
+ controller_dispatch_web_service_request
+ end
+ EOS
+ end
+ end
+ base.add_web_service_definition_callback do |klass, name, info|
+ if klass.web_service_dispatching_mode == :delegated
+ klass.class_eval <<-EOS
+ def #{name}
+ controller_dispatch_web_service_request
+ end
+ EOS
end
end
base.extend(ClassMethods)
+ base.send(:include, ActionWebService::Dispatcher::ActionController::Invocation)
end
- module ClassMethods
+ module ClassMethods # :nodoc:
def inherited(child)
- inherited_without_wsdl(child)
- child.send(:include, ActionWebService::Router::Wsdl::InstanceMethods)
+ inherited_without_action_controller(child)
+ child.send(:include, ActionWebService::Dispatcher::ActionController::WsdlGeneration)
end
end
- module InstanceMethods # :nodoc:
+ module Invocation # :nodoc:
+ private
+ def controller_dispatch_web_service_request
+ request, response, elapsed, exception = dispatch_web_service_request(@request)
+ if response
+ begin
+ log_request(request)
+ log_error(exception) if exception && logger
+ log_response(response, elapsed)
+ response_options = { :type => response.content_type, :disposition => 'inline' }
+ send_data(response.raw_body, response_options)
+ rescue Exception => e
+ log_error(e) unless logger.nil?
+ render_text("Internal protocol error", "500 Internal Server Error")
+ end
+ else
+ logger.error("No response available") unless logger.nil?
+ render_text("Internal protocol error", "500 Internal Server Error")
+ end
+ end
+
+ def before_direct_invoke(request)
+ before_direct_invoke_without_action_controller(request)
+ @params ||= {}
+ signature = request.signature
+ if signature && (expects = request.signature[:expects])
+ (0..(@method_params.size-1)).each do |i|
+ if expects[i].is_a?(Hash)
+ @params[expects[i].keys[0].to_s] = @method_params[i]
+ else
+ @params['param%d' % i] = @method_params[i]
+ end
+ end
+ end
+ @params['action'] = request.method_name.to_s
+ @session ||= {}
+ @assigns ||= {}
+ return nil if before_action == false
+ true
+ end
+
+ def after_direct_invoke(request)
+ after_direct_invoke_without_action_controller(request)
+ after_action
+ end
+
+ def log_request(request)
+ unless logger.nil? || request.nil?
+ logger.debug("\nWeb Service Request:")
+ indented = request.raw_body.split(/\n/).map{|x| " #{x}"}.join("\n")
+ logger.debug(indented)
+ end
+ end
+
+ def log_response(response, elapsed)
+ unless logger.nil? || response.nil?
+ logger.debug("\nWeb Service Response (%f):" % elapsed)
+ indented = response.raw_body.split(/\n/).map{|x| " #{x}"}.join("\n")
+ logger.debug(indented)
+ end
+ end
+
+ unless method_defined?(:logger)
+ def logger; @logger; end
+ end
+ end
+
+ module WsdlGeneration # :nodoc:
XsdNs = 'http://www.w3.org/2001/XMLSchema'
WsdlNs = 'http://schemas.xmlsoap.org/wsdl/'
SoapNs = 'http://schemas.xmlsoap.org/wsdl/soap/'
@@ -28,7 +119,7 @@ module ActionWebService # :nodoc:
case @request.method
when :get
begin
- host_name = @request.env['HTTP_HOST']||@request.env['SERVER_NAME']
+ host_name = @request.env['HTTP_HOST'] || @request.env['SERVER_NAME']
uri = "http://#{host_name}/#{controller_name}/"
soap_action_base = "/#{controller_name}"
xml = to_wsdl(self, uri, soap_action_base)
diff --git a/actionwebservice/lib/action_web_service/invocation.rb b/actionwebservice/lib/action_web_service/invocation.rb
index 64d3e8d524..62f38b8ecd 100644
--- a/actionwebservice/lib/action_web_service/invocation.rb
+++ b/actionwebservice/lib/action_web_service/invocation.rb
@@ -1,9 +1,5 @@
module ActionWebService # :nodoc:
module Invocation # :nodoc:
- ConcreteInvocation = :concrete
- VirtualInvocation = :virtual
- UnpublishedConcreteInvocation = :unpublished_concrete
-
class InvocationError < ActionWebService::ActionWebServiceError # :nodoc:
end
@@ -137,31 +133,15 @@ module ActionWebService # :nodoc:
end
end
- def perform_invocation_with_interception(invocation, &block)
- return if before_invocation(invocation.method_name, invocation.params, &block) == false
- result = perform_invocation_without_interception(invocation)
- after_invocation(invocation.method_name, invocation.params, result)
- result
+ def perform_invocation_with_interception(method_name, params, &block)
+ return if before_invocation(method_name, params, &block) == false
+ return_value = perform_invocation_without_interception(method_name, params)
+ after_invocation(method_name, params, return_value)
+ return_value
end
- def perform_invocation(invocation)
- if invocation.concrete?
- unless self.respond_to?(invocation.method_name) && \
- self.class.web_service_api.has_api_method?(invocation.method_name)
- raise InvocationError, "no such web service method '#{invocation.method_name}' on service object"
- end
- end
- params = invocation.params
- if invocation.concrete? || invocation.unpublished_concrete?
- self.send(invocation.method_name, *params)
- else
- if invocation.block
- params = invocation.block_params + params
- invocation.block.call(invocation.public_method_name, *params)
- else
- self.send(invocation.method_name, *params)
- end
- end
+ def perform_invocation(method_name, params)
+ send(method_name, *params)
end
def before_invocation(name, args, &block)
@@ -221,32 +201,5 @@ module ActionWebService # :nodoc:
end
end
end
-
- class InvocationRequest # :nodoc:
- attr_accessor :type
- attr :public_method_name
- attr_accessor :method_name
- attr_accessor :params
- attr_accessor :block
- attr :block_params
-
- def initialize(type, public_method_name, method_name, params=nil)
- @type = type
- @public_method_name = public_method_name
- @method_name = method_name
- @params = params || []
- @block = nil
- @block_params = []
- end
-
- def concrete?
- @type == ConcreteInvocation ? true : false
- end
-
- def unpublished_concrete?
- @type == UnpublishedConcreteInvocation ? true : false
- end
- end
-
end
end
diff --git a/actionwebservice/lib/action_web_service/protocol.rb b/actionwebservice/lib/action_web_service/protocol.rb
index 733787136a..b15e850676 100644
--- a/actionwebservice/lib/action_web_service/protocol.rb
+++ b/actionwebservice/lib/action_web_service/protocol.rb
@@ -1,4 +1,4 @@
require 'action_web_service/protocol/abstract'
require 'action_web_service/protocol/registry'
-require 'action_web_service/protocol/soap'
-require 'action_web_service/protocol/xmlrpc'
+require 'action_web_service/protocol/soap_protocol'
+require 'action_web_service/protocol/xmlrpc_protocol'
diff --git a/actionwebservice/lib/action_web_service/protocol/soap.rb b/actionwebservice/lib/action_web_service/protocol/soap_protocol.rb
index 3c527fea93..3c527fea93 100644
--- a/actionwebservice/lib/action_web_service/protocol/soap.rb
+++ b/actionwebservice/lib/action_web_service/protocol/soap_protocol.rb
diff --git a/actionwebservice/lib/action_web_service/protocol/xmlrpc.rb b/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb
index 414bcfdbf7..1addccba56 100644
--- a/actionwebservice/lib/action_web_service/protocol/xmlrpc.rb
+++ b/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb
@@ -54,7 +54,6 @@ module ActionWebService # :nodoc:
def initialize(container_class)
super(container_class)
- container_class.write_inheritable_hash('default_system_methods', XmlRpcProtocol => method(:xmlrpc_default_system_handler))
end
def unmarshal_request(protocol_request)
@@ -153,20 +152,6 @@ module ActionWebService # :nodoc:
end
private
- def xmlrpc_default_system_handler(name, service_class, *args)
- case name
- when 'system.listMethods'
- methods = []
- api = service_class.web_service_api
- api.api_methods.each do |name, info|
- methods << api.public_api_method_name(name)
- end
- methods.sort
- else
- throw :try_default
- end
- end
-
def check_array_types(signature)
signature.map{|x| x.is_a?(Array) ? Array : x}
end
diff --git a/actionwebservice/lib/action_web_service/router.rb b/actionwebservice/lib/action_web_service/router.rb
deleted file mode 100644
index 4bfb0bc8b7..0000000000
--- a/actionwebservice/lib/action_web_service/router.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require 'action_web_service/router/action_controller'
-require 'action_web_service/router/wsdl'
diff --git a/actionwebservice/lib/action_web_service/router/action_controller.rb b/actionwebservice/lib/action_web_service/router/action_controller.rb
deleted file mode 100644
index 591fe4e232..0000000000
--- a/actionwebservice/lib/action_web_service/router/action_controller.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-module ActionWebService # :nodoc:
- module Router # :nodoc:
- module ActionController # :nodoc:
- def self.append_features(base) # :nodoc:
- base.add_web_service_api_callback do |container_class, api|
- if container_class.web_service_dispatching_mode == :direct
- container_class.class_eval <<-EOS
- def api
- process_action_service_request
- end
- EOS
- end
- end
- base.add_web_service_definition_callback do |klass, name, info|
- if klass.web_service_dispatching_mode == :delegated
- klass.class_eval <<-EOS
- def #{name}
- process_action_service_request
- end
- EOS
- end
- end
- base.send(:include, ActionWebService::Router::ActionController::InstanceMethods)
- end
-
- module InstanceMethods # :nodoc:
- private
- def process_action_service_request
- protocol_request = nil
- begin
- begin
- protocol_request = probe_request_protocol(self.request)
- rescue Exception => e
- unless logger.nil?
- logger.error "Invalid request: #{e.message}"
- logger.error self.request.raw_post
- end
- raise
- end
- if protocol_request
- log_request(protocol_request)
- protocol_response = dispatch_web_service_request(protocol_request)
- log_response(protocol_response)
- response_options = {
- :type => protocol_response.content_type,
- :disposition => 'inline'
- }
- send_data(protocol_response.raw_body, response_options)
- else
- logger.fatal "Invalid Action Web Service service or method requested" unless logger.nil?
- render_text 'Internal protocol error', "500 Invalid service/method"
- end
- rescue Exception => e
- log_error e unless logger.nil?
- exc_response = nil
- case web_service_dispatching_mode
- when :direct
- if self.class.web_service_exception_reporting
- exc_response = protocol_request.protocol.marshal_exception(e)
- end
- when :delegated
- web_service = web_service_object(protocol_request.service_name) rescue nil
- if web_service && web_service.class.web_service_exception_reporting
- exc_response = protocol_request.protocol.marshal_exception(e) rescue nil
- end
- end
- if exc_response
- response_options = {
- :type => exc_response.content_type,
- :disposition => 'inline'
- }
- log_response exc_response
- send_data(exc_response.raw_body, response_options)
- else
- render_text 'Internal protocol error', "500 #{e.message}"
- end
- end
- end
-
- def log_request(protocol_request)
- unless logger.nil?
- web_service_name = protocol_request.web_service_name
- method_name = protocol_request.public_method_name
- logger.info "\nProcessing Action Web Service Request: #{web_service_name}##{method_name}"
- logger.info "Raw Request Body:"
- logger.info protocol_request.raw_body
- end
- end
-
- def log_response(protocol_response)
- unless logger.nil?
- logger.info "\nRaw Response Body:"
- logger.info protocol_response.raw_body
- end
- end
- end
- end
- end
-end
diff --git a/actionwebservice/test/abstract_client.rb b/actionwebservice/test/abstract_client.rb
index 0197b87d63..b443fa8ffb 100644
--- a/actionwebservice/test/abstract_client.rb
+++ b/actionwebservice/test/abstract_client.rb
@@ -71,7 +71,7 @@ module ClientTest
end
def dispatch_request(protocol_request)
- dispatch_web_service_request(protocol_request)
+ dispatch_protocol_request(protocol_request)
end
end
diff --git a/actionwebservice/test/router_action_controller_test.rb b/actionwebservice/test/dispatcher_action_controller_test.rb
index 4f6d40e738..11ab21c6a6 100644
--- a/actionwebservice/test/router_action_controller_test.rb
+++ b/actionwebservice/test/dispatcher_action_controller_test.rb
@@ -1,11 +1,18 @@
require File.dirname(__FILE__) + '/abstract_soap'
require 'wsdl/parser'
-module RouterActionControllerTest
+module DispatcherActionControllerTest
class API < ActionWebService::API::Base
api_method :add, :expects => [:int, :int], :returns => [:int]
end
+ class DirectAPI < ActionWebService::API::Base
+ api_method :add, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int]
+ api_method :before_filtered
+ api_method :after_filtered, :returns => [:int]
+ api_method :thrower
+ end
+
class Service < ActionWebService::Base
web_service_api API
@@ -15,21 +22,20 @@ module RouterActionControllerTest
@added = a + b
end
end
-
- class DelegatedController < ActionController::Base
+
+ class AbstractController < ActionController::Base
+ def generate_wsdl(container, uri, soap_action_base)
+ to_wsdl(container, uri, soap_action_base)
+ end
+ end
+
+ class DelegatedController < AbstractController
web_service_dispatching_mode :delegated
web_service(:test_service) { @service ||= Service.new; @service }
end
-
- class DirectAPI < ActionWebService::API::Base
- api_method :add, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int]
- api_method :before_filtered
- api_method :after_filtered, :returns => [:int]
- api_method :thrower
- end
-
- class DirectController < ActionController::Base
+
+ class DirectController < AbstractController
web_service_api DirectAPI
web_service_dispatching_mode :direct
@@ -78,20 +84,22 @@ module RouterActionControllerTest
end
end
-class TC_RouterActionController < AbstractSoapTest
- def test_direct_routing
- @container = RouterActionControllerTest::DirectController.new
+class TC_DispatcherActionController < AbstractSoapTest
+ include DispatcherActionControllerTest
+
+ def test_direct_dispatching
+ @container = DirectController.new
assert(do_soap_call('Add', 20, 50) == 70)
assert(@container.added == 70)
end
def test_direct_entrypoint
- @container = RouterActionControllerTest::DirectController.new
+ @container = DirectController.new
assert(@container.respond_to?(:api))
end
def test_direct_filtering
- @container = RouterActionControllerTest::DirectController.new
+ @container = DirectController.new
assert(@container.before_filter_called == false)
assert(@container.before_filter_target_called == false)
assert(do_soap_call('BeforeFiltered').nil?)
@@ -104,14 +112,14 @@ class TC_RouterActionController < AbstractSoapTest
assert(@container.after_filter_target_called == true)
end
- def test_delegated_routing
- @container = RouterActionControllerTest::DelegatedController.new
+ def test_delegated_dispatching
+ @container = DelegatedController.new
assert(do_soap_call('Add', 50, 80) == 130)
assert(service.added == 130)
end
def test_exception_marshaling
- @container = RouterActionControllerTest::DirectController.new
+ @container = DirectController.new
result = do_soap_call('Thrower')
exception = result.detail
assert(exception.cause.is_a?(RuntimeError))
@@ -122,9 +130,21 @@ class TC_RouterActionController < AbstractSoapTest
end
end
+ def test_wsdl_generation
+ ensure_valid_wsdl_generation DelegatedController.new
+ ensure_valid_wsdl_generation DirectController.new
+ end
+
+ def
+
+ def test_wsdl_action
+ ensure_valid_wsdl_action DelegatedController.new
+ ensure_valid_wsdl_action DirectController.new
+ end
+
protected
def service_name
- @container.is_a?(RouterActionControllerTest::DelegatedController) ? 'test_service' : 'api'
+ @container.is_a?(DelegatedController) ? 'test_service' : 'api'
end
def service
@@ -136,4 +156,31 @@ class TC_RouterActionController < AbstractSoapTest
response = @container.process(test_request, test_response)
end
end
+
+ def ensure_valid_wsdl_generation(controller)
+ wsdl = controller.generate_wsdl(controller, 'http://localhost:3000/test/', '/test')
+ ensure_valid_wsdl(wsdl)
+ end
+
+ def ensure_valid_wsdl(wsdl)
+ definitions = WSDL::Parser.new.parse(wsdl)
+ assert(definitions.is_a?(WSDL::Definitions))
+ definitions.bindings.each do |binding|
+ assert(binding.name.name.index(':').nil?)
+ end
+ definitions.services.each do |service|
+ service.ports.each do |port|
+ assert(port.name.name.index(':').nil?)
+ end
+ end
+ end
+
+ def ensure_valid_wsdl_action(controller)
+ test_request = ActionController::TestRequest.new({ 'action' => 'wsdl' })
+ test_request.env['REQUEST_METHOD'] = 'GET'
+ test_request.env['HTTP_HOST'] = 'localhost:3000'
+ test_response = ActionController::TestResponse.new
+ wsdl = controller.process(test_request, test_response).body
+ ensure_valid_wsdl(wsdl)
+ end
end
diff --git a/actionwebservice/test/invocation_test.rb b/actionwebservice/test/invocation_test.rb
index 8ca80ec8f2..0d519bf770 100644
--- a/actionwebservice/test/invocation_test.rb
+++ b/actionwebservice/test/invocation_test.rb
@@ -58,9 +58,6 @@ module InvocationTest
def only_two
end
- def not_public
- end
-
protected
def intercept_before(name, args)
@before_invoked = name
@@ -90,10 +87,7 @@ class TC_Invocation < Test::Unit::TestCase
def test_invocation
assert(perform_invocation(:add, 5, 10) == 15)
assert(perform_invocation(:transmogrify, "hello") == "HELLO")
- assert_raises(InvocationError) do
- perform_invocation(:not_public)
- end
- assert_raises(InvocationError) do
+ assert_raises(NoMethodError) do
perform_invocation(:nonexistent_method_xyzzy)
end
end
@@ -150,9 +144,6 @@ class TC_Invocation < Test::Unit::TestCase
private
def perform_invocation(method_name, *args, &block)
- public_method_name = @service.class.web_service_api.public_api_method_name(method_name)
- args ||= []
- request = InvocationRequest.new(ConcreteInvocation, public_method_name, method_name, args)
- @service.perform_invocation(request, &block)
+ @service.perform_invocation(method_name, args, &block)
end
end
diff --git a/actionwebservice/test/protocol_soap_test.rb b/actionwebservice/test/protocol_soap_test.rb
index 1130dff3a7..c55b7f55af 100644
--- a/actionwebservice/test/protocol_soap_test.rb
+++ b/actionwebservice/test/protocol_soap_test.rb
@@ -12,6 +12,13 @@ module ProtocolSoapTest
end
end
+ class EmptyAPI < ActionWebService::API::Base
+ end
+
+ class EmptyService < ActionWebService::Base
+ web_service_api EmptyAPI
+ end
+
class API < ActionWebService::API::Base
api_method :argument_passing, :expects => [{:int=>:int}, {:string=>:string}, {:array=>[:int]}], :returns => [:bool]
api_method :array_returner, :returns => [[:int]]
@@ -72,26 +79,19 @@ module ProtocolSoapTest
end
end
- class AbstractContainer
- include ActionWebService::API
- include ActionWebService::Container
- include ActionWebService::Protocol::Registry
- include ActionWebService::Protocol::Soap
-
+ class AbstractContainer < ActionController::Base
wsdl_service_name 'Test'
- def protocol_request(request)
- probe_request_protocol(request)
- end
-
- def dispatch_request(protocol_request)
- dispatch_web_service_request(protocol_request)
+ def dispatch_request(request)
+ protocol_request = probe_request_protocol(request)
+ dispatch_protocol_request(protocol_request)
end
end
class DelegatedContainer < AbstractContainer
web_service_dispatching_mode :delegated
web_service :protocol_soap_service, Service.new
+ web_service :empty_service, EmptyService.new
end
class DirectContainer < AbstractContainer
@@ -144,12 +144,18 @@ module ProtocolSoapTest
nil
end
end
+
+ class EmptyContainer < AbstractContainer
+ web_service_dispatching_mode :delegated
+ web_service :empty_service, EmptyService.new
+ end
end
class TC_ProtocolSoap < AbstractSoapTest
def setup
@delegated_container = ProtocolSoapTest::DelegatedContainer.new
@direct_container = ProtocolSoapTest::DirectContainer.new
+ @empty_container = ProtocolSoapTest::EmptyContainer.new
end
def test_argument_passing
@@ -180,6 +186,13 @@ class TC_ProtocolSoap < AbstractSoapTest
end
end
+ def test_nonexistent_method
+ @container = @empty_container
+ assert_raises(ActionWebService::Dispatcher::DispatcherError) do
+ do_soap_call('NonexistentMethod')
+ end
+ end
+
def test_exception_thrower
in_all_containers do
assert_raises(RuntimeError) do
@@ -203,15 +216,29 @@ class TC_ProtocolSoap < AbstractSoapTest
protected
def service_name
- @container == @direct_container ? 'api' : 'protocol_soap_service'
+ case
+ when @container == @direct_container
+ 'api'
+ when @container == @delegated_container
+ 'protocol_soap_service'
+ when @container == @empty_container
+ 'empty_service'
+ end
end
def service
- @container == @direct_container ? @container : @container.web_service_object(:protocol_soap_service)
+ case
+ when @container == @direct_container
+ @container
+ when @container == @delegated_container
+ @container.web_service_object(:protocol_soap_service)
+ when @container == @empty_container
+ @container.web_service_object(:empty_service)
+ end
end
def in_all_containers(&block)
- [@direct_container].each do |container|
+ [@direct_container, @delegated_container].each do |container|
@container = container
block.call
end
@@ -219,8 +246,7 @@ class TC_ProtocolSoap < AbstractSoapTest
def do_soap_call(public_method_name, *args)
super(public_method_name, *args) do |test_request, test_response|
- protocol_request = @container.protocol_request(test_request)
- @container.dispatch_request(protocol_request)
+ @container.dispatch_request(test_request)
end
end
end
diff --git a/actionwebservice/test/protocol_xmlrpc_test.rb b/actionwebservice/test/protocol_xmlrpc_test.rb
index 7dc5cf0252..cda0bba6d3 100644
--- a/actionwebservice/test/protocol_xmlrpc_test.rb
+++ b/actionwebservice/test/protocol_xmlrpc_test.rb
@@ -79,18 +79,13 @@ module ProtocolXmlRpcTest
$service = Service.new
- class Container
- include ActionWebService::Container
- include ActionWebService::Protocol::Registry
- include ActionWebService::Protocol::Soap
- include ActionWebService::Protocol::XmlRpc
-
+ class Container < ActionController::Base
def protocol_request(request)
probe_request_protocol(request)
end
def dispatch_request(protocol_request)
- dispatch_web_service_request(protocol_request)
+ dispatch_protocol_request(protocol_request)
end
web_service :xmlrpc, $service
@@ -136,11 +131,6 @@ class TC_ProtocolXmlRpc < Test::Unit::TestCase
assert($service.default_args == ['test', [1, 2], {'name'=>'value'}])
end
- def test_xmlrpc_introspection
- retval = do_xmlrpc_call('system.listMethods', 'test', [1, 2], {'name'=>'value'})
- assert(retval == [true, ["Add", "ArrayReturner", "HashReturner", "SomethingHash", "StructArrayReturner"]])
- end
-
private
def do_xmlrpc_call(public_method_name, *args)
service_name = 'xmlrpc'
diff --git a/actionwebservice/test/router_wsdl_test.rb b/actionwebservice/test/router_wsdl_test.rb
deleted file mode 100644
index a441e73f37..0000000000
--- a/actionwebservice/test/router_wsdl_test.rb
+++ /dev/null
@@ -1,100 +0,0 @@
-require File.dirname(__FILE__) + '/abstract_unit'
-require 'wsdl/parser'
-
-module RouterWsdlTest
- class Person < ActionWebService::Struct
- member :id, Integer
- member :names, [String]
- member :lastname, String
- member :deleted, TrueClass
- end
-
- class API < ActionWebService::API::Base
- api_method :add, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int]
- api_method :find_people, :returns => [[Person]]
- api_method :nil_returner
- end
-
- class Service < ActionWebService::Base
- web_service_api API
-
- def add(a, b)
- a + b
- end
-
- def find_people
- []
- end
-
- def nil_returner
- end
- end
-
- class AbstractController < ActionController::Base
- def generate_wsdl(container, uri, soap_action_base)
- to_wsdl(container, uri, soap_action_base)
- end
- end
-
- class DirectController < AbstractController
- web_service_api API
-
- def add
- end
-
- def find_people
- end
-
- def nil_returner
- end
- end
-
- class DelegatedController < AbstractController
- web_service_dispatching_mode :delegated
- web_service(:test_service) { Service.new }
- end
-end
-
-class TC_RouterWsdl < Test::Unit::TestCase
- include RouterWsdlTest
-
- def test_wsdl_generation
- ensure_valid_generation DelegatedController.new
- ensure_valid_generation DirectController.new
- end
-
- def
-
- def test_wsdl_action
- ensure_valid_wsdl_action DelegatedController.new
- ensure_valid_wsdl_action DirectController.new
- end
-
- protected
- def ensure_valid_generation(controller)
- wsdl = controller.generate_wsdl(controller, 'http://localhost:3000/test/', '/test')
- ensure_valid_wsdl(wsdl)
- end
-
- def ensure_valid_wsdl(wsdl)
- definitions = WSDL::Parser.new.parse(wsdl)
- assert(definitions.is_a?(WSDL::Definitions))
- definitions.bindings.each do |binding|
- assert(binding.name.name.index(':').nil?)
- end
- definitions.services.each do |service|
- service.ports.each do |port|
- assert(port.name.name.index(':').nil?)
- end
- end
- end
-
- def ensure_valid_wsdl_action(controller)
- test_request = ActionController::TestRequest.new({ 'action' => 'wsdl' })
- test_request.env['REQUEST_METHOD'] = 'GET'
- test_request.env['HTTP_HOST'] = 'localhost:3000'
- test_response = ActionController::TestResponse.new
- wsdl = controller.process(test_request, test_response).body
- ensure_valid_wsdl(wsdl)
- end
-end