summaryrefslogtreecommitdiff
path: root/lib/soap/rpc/soaplet.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/soap/rpc/soaplet.rb')
-rw-r--r--lib/soap/rpc/soaplet.rb219
1 files changed, 64 insertions, 155 deletions
diff --git a/lib/soap/rpc/soaplet.rb b/lib/soap/rpc/soaplet.rb
index 8f18c53d3a..4d2538f0b3 100644
--- a/lib/soap/rpc/soaplet.rb
+++ b/lib/soap/rpc/soaplet.rb
@@ -1,5 +1,5 @@
# SOAP4R - SOAP handler servlet for WEBrick
-# Copyright (C) 2001, 2002, 2003, 2004 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
+# Copyright (C) 2001-2005 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
# redistribute it and/or modify it under the same terms of Ruby's license;
@@ -14,7 +14,23 @@ begin
require 'stringio'
require 'zlib'
rescue LoadError
- STDERR.puts "Loading stringio or zlib failed. No gzipped response support." if $DEBUG
+ warn("Loading stringio or zlib failed. No gzipped response supported.") if $DEBUG
+end
+
+
+warn("Overriding WEBrick::Log#debug") if $DEBUG
+require 'webrick/log'
+module WEBrick
+ class Log < BasicLog
+ alias __debug debug
+ def debug(msg = nil)
+ if block_given? and msg.nil?
+ __debug(yield)
+ else
+ __debug(msg)
+ end
+ end
+ end
end
@@ -24,60 +40,27 @@ module RPC
class SOAPlet < WEBrick::HTTPServlet::AbstractServlet
public
- attr_reader :app_scope_router
attr_reader :options
- def initialize
- @rpc_router_map = {}
- @app_scope_router = ::SOAP::RPC::Router.new(self.class.name)
- @headerhandlerfactory = []
- @app_scope_headerhandler = nil
+ def initialize(router = nil)
+ @router = router || ::SOAP::RPC::Router.new(self.class.name)
@options = {}
+ @config = {}
end
- def allow_content_encoding_gzip=(allow)
- @options[:allow_content_encoding_gzip] = allow
- end
-
- # Add servant factory whose object has request scope. A servant object is
- # instanciated for each request.
- #
- # Bear in mind that servant factories are distinguished by HTTP SOAPAction
- # header in request. Client which calls request-scoped servant must have a
- # SOAPAction header which is a namespace of the servant factory.
- # I mean, use Driver#add_method_with_soapaction instead of Driver#add_method
- # at client side.
- #
- # A factory must respond to :create.
- #
- def add_rpc_request_servant(factory, namespace, mapping_registry = nil)
- unless factory.respond_to?(:create)
- raise TypeError.new("factory must respond to 'create'")
- end
- router = setup_rpc_request_router(namespace)
- router.factory = factory
- router.mapping_registry = mapping_registry
- end
-
- # Add servant object which has application scope.
- def add_rpc_servant(obj, namespace)
- router = @app_scope_router
- SOAPlet.add_rpc_servant_to_router(router, obj, namespace)
- add_rpc_router(namespace, router)
+ # for backward compatibility
+ def app_scope_router
+ @router
end
- alias add_servant add_rpc_servant
- def add_rpc_request_headerhandler(factory)
- unless factory.respond_to?(:create)
- raise TypeError.new("factory must respond to 'create'")
- end
- @headerhandlerfactory << factory
+ # for backward compatibility
+ def add_servant(obj, namespace)
+ @router.add_rpc_servant(obj, namespace)
end
- def add_rpc_headerhandler(obj)
- @app_scope_headerhandler = obj
+ def allow_content_encoding_gzip=(allow)
+ @options[:allow_content_encoding_gzip] = allow
end
- alias add_headerhandler add_rpc_headerhandler
###
## Servlet interfaces for WEBrick.
@@ -93,111 +76,63 @@ public
def do_GET(req, res)
res.header['Allow'] = 'POST'
- raise WEBrick::HTTPStatus::MethodNotAllowed, "GET request not allowed."
+ raise WEBrick::HTTPStatus::MethodNotAllowed, "GET request not allowed"
end
def do_POST(req, res)
- @config[:Logger].debug { "SOAP request: " + req.body }
- soapaction = parse_soapaction(req.meta_vars['HTTP_SOAPACTION'])
- router = lookup_router(soapaction)
- with_headerhandler(router) do |router|
- begin
- conn_data = ::SOAP::StreamHandler::ConnectionData.new
- conn_data.receive_string = req.body
- conn_data.receive_contenttype = req['content-type']
- conn_data = router.route(conn_data)
- res['content-type'] = conn_data.send_contenttype
- if conn_data.is_fault
- res.status = WEBrick::HTTPStatus::RC_INTERNAL_SERVER_ERROR
- end
- if outstring = encode_gzip(req, conn_data.send_string)
- res['content-encoding'] = 'gzip'
- res['content-length'] = outstring.size
- res.body = outstring
- else
- res.body = conn_data.send_string
- end
- rescue Exception => e
- conn_data = router.create_fault_response(e)
- res.status = WEBrick::HTTPStatus::RC_INTERNAL_SERVER_ERROR
- res.body = conn_data.send_string
- res['content-type'] = conn_data.send_contenttype || "text/xml"
- end
+ logger.debug { "SOAP request: " + req.body } if logger
+ begin
+ conn_data = ::SOAP::StreamHandler::ConnectionData.new
+ setup_req(conn_data, req)
+ conn_data = @router.route(conn_data)
+ setup_res(conn_data, req, res)
+ rescue Exception => e
+ conn_data = @router.create_fault_response(e)
+ res.status = WEBrick::HTTPStatus::RC_INTERNAL_SERVER_ERROR
+ res.body = conn_data.send_string
+ res['content-type'] = conn_data.send_contenttype || "text/xml"
end
-
if res.body.is_a?(IO)
res.chunked = true
- @config[:Logger].debug { "SOAP response: (chunked response not logged)" }
+ logger.debug { "SOAP response: (chunked response not logged)" } if logger
else
- @config[:Logger].debug { "SOAP response: " + res.body }
+ logger.debug { "SOAP response: " + res.body } if logger
end
end
private
- class RequestRouter < ::SOAP::RPC::Router
- attr_accessor :factory
-
- def initialize(style = :rpc, namespace = nil)
- super(namespace)
- @style = style
- @namespace = namespace
- @factory = nil
- end
-
- def route(soap_string)
- obj = @factory.create
- namespace = self.actor
- router = ::SOAP::RPC::Router.new(@namespace)
- if @style == :rpc
- SOAPlet.add_rpc_servant_to_router(router, obj, namespace)
- else
- raise RuntimeError.new("'document' style not supported.")
- end
- router.route(soap_string)
- end
- end
-
- def setup_rpc_request_router(namespace)
- router = @rpc_router_map[namespace] || RequestRouter.new(:rpc, namespace)
- add_rpc_router(namespace, router)
- router
+ def logger
+ @config[:Logger]
end
- def add_rpc_router(namespace, router)
- @rpc_router_map[namespace] = router
+ def setup_req(conn_data, req)
+ conn_data.receive_string = req.body
+ conn_data.receive_contenttype = req['content-type']
+ conn_data.soapaction = parse_soapaction(req.meta_vars['HTTP_SOAPACTION'])
end
- def parse_soapaction(soapaction)
- if /^"(.*)"$/ =~ soapaction
- soapaction = $1
- end
- if soapaction.empty?
- return nil
+ def setup_res(conn_data, req, res)
+ res['content-type'] = conn_data.send_contenttype
+ if conn_data.is_fault
+ res.status = WEBrick::HTTPStatus::RC_INTERNAL_SERVER_ERROR
end
- soapaction
- end
-
- def lookup_router(namespace)
- if namespace
- @rpc_router_map[namespace] || @app_scope_router
+ if outstring = encode_gzip(req, conn_data.send_string)
+ res['content-encoding'] = 'gzip'
+ res['content-length'] = outstring.size
+ res.body = outstring
else
- @app_scope_router
+ res.body = conn_data.send_string
end
end
- def with_headerhandler(router)
- if @app_scope_headerhandler and
- !router.headerhandler.include?(@app_scope_headerhandler)
- router.headerhandler.add(@app_scope_headerhandler)
- end
- handlers = @headerhandlerfactory.collect { |f| f.create }
- begin
- handlers.each { |h| router.headerhandler.add(h) }
- yield(router)
- ensure
- handlers.each { |h| router.headerhandler.delete(h) }
+ def parse_soapaction(soapaction)
+ if !soapaction.nil? and !soapaction.empty?
+ if /^"(.+)"$/ =~ soapaction
+ return $1
+ end
end
+ nil
end
def encode_gzip(req, outstring)
@@ -219,32 +154,6 @@ private
req['accept-encoding'] and
req['accept-encoding'].split(/,\s*/).include?('gzip')
end
-
- class << self
- public
- def add_rpc_servant_to_router(router, obj, namespace)
- ::SOAP::RPC.defined_methods(obj).each do |name|
- begin
- add_rpc_servant_method_to_router(router, obj, namespace, name)
- rescue SOAP::RPC::MethodDefinitionError => e
- p e if $DEBUG
- end
- end
- end
-
- def add_rpc_servant_method_to_router(router, obj, namespace, name,
- style = :rpc, use = :encoded)
- qname = XSD::QName.new(namespace, name)
- soapaction = nil
- method = obj.method(name)
- param_def = ::SOAP::RPC::SOAPMethod.create_param_def(
- (1..method.arity.abs).collect { |i| "p#{ i }" })
- opt = {}
- opt[:request_style] = opt[:response_style] = style
- opt[:request_use] = opt[:response_use] = use
- router.add_operation(qname, soapaction, obj, name, param_def, opt)
- end
- end
end