summaryrefslogtreecommitdiff
path: root/lib/soap/rpc
diff options
context:
space:
mode:
authornahi <nahi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-01-06 02:20:51 +0000
committernahi <nahi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-01-06 02:20:51 +0000
commitff1b89a96d0f103ff0c917c458ddd3e36e9b3718 (patch)
tree5449bd61cebdf6486cb443c0013a8573204fb50c /lib/soap/rpc
parent8a8dd6519948eaf207f03c12152fc160de7370a2 (diff)
* import soap4r/1.5.2;
* lib/soap/{attachment.rb,baseData.rb,encodingstyle/soapHandler.rb}: introduce SOAPExternalReference class as a referenct to SOAPEnvelope external content. * lib/soap/{attachment.rb,mimemessage.rb}: great SwA (SOAP messages with Attachments) support code by Jamie Herre. * lib/soap/{element.rb,marshal.rb,parser.rb,processor.rb, streamHandler.rb,wsdlDriver.rb}: SwA support. * lib/soap/rpc/{cgistub.rb,driver.rb,element.rb,proxy.rb,router.rb, soaplet.rb}: SwA support and refactoring. * lib/soap/generator.rb, lib/soap/mapping/mapping.rb: follow SOAPReference#initialize signature change. * lib/soap/mapping/factory.rb: deleted unused methods. * lib/soap/mapping/rubytypeFactory.rb: do no ignore case while xsi:type string <-> Ruby class name matching. * lib/xsd/datatypes.rb: check the smallest positive non-zero single-precision float exactly instead of packing with "f". [ruby-talk:88822] * test/soap/test_basetype.rb, test/xsd/test_xsd.rb: use 1.402e-45, not 1.4e-45. 1.4e-45 is smaller than 2 ** -149... * test/soap/test_basetype.rb, test/soap/marshal/test_marshal.rb, test/xsd/test_xsd.rb: use "(-1.0 / (1.0 / 0.0))" instead of "-0.0". * test/soap/test_streamhandler.rb: revert to the previous test that warns "basic_auth unsupported under net/http". git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5384 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/soap/rpc')
-rw-r--r--lib/soap/rpc/cgistub.rb40
-rw-r--r--lib/soap/rpc/driver.rb12
-rw-r--r--lib/soap/rpc/element.rb5
-rw-r--r--lib/soap/rpc/proxy.rb52
-rw-r--r--lib/soap/rpc/router.rb82
-rw-r--r--lib/soap/rpc/soaplet.rb28
6 files changed, 156 insertions, 63 deletions
diff --git a/lib/soap/rpc/cgistub.rb b/lib/soap/rpc/cgistub.rb
index 2377f343b5..4fc8b98cee 100644
--- a/lib/soap/rpc/cgistub.rb
+++ b/lib/soap/rpc/cgistub.rb
@@ -40,7 +40,6 @@ class CGIStub < Logger::Application
@method = ENV['REQUEST_METHOD']
@size = ENV['CONTENT_LENGTH'].to_i || 0
@contenttype = ENV['CONTENT_TYPE']
- @charset = nil
@soapaction = ENV['HTTP_SOAPAction']
@source = stream
@body = nil
@@ -48,7 +47,6 @@ class CGIStub < Logger::Application
def init
validate
- @charset = StreamHandler.parse_media_type(@contenttype)
@body = @source.read(@size)
self
end
@@ -61,8 +59,8 @@ class CGIStub < Logger::Application
@soapaction
end
- def charset
- @charset
+ def contenttype
+ @contenttype
end
def to_s
@@ -142,8 +140,8 @@ class CGIStub < Logger::Application
@router.add_method(receiver, qname, nil, name, param_def)
end
- def route(request_string, charset)
- @router.route(request_string, charset)
+ def route(conn_data)
+ @router.route(conn_data)
end
def create_fault_response(e)
@@ -157,32 +155,30 @@ private
httpversion = WEBrick::HTTPVersion.new('1.0')
@response = WEBrick::HTTPResponse.new({:HTTPVersion => httpversion})
+ conn_data = nil
begin
log(INFO) { "Received a request from '#{ @remote_user }@#{ @remote_host }'." }
# SOAP request parsing.
@request = SOAPRequest.new.init
@response['Status'] = 200
- req_charset = @request.charset
- req_string = @request.dump
- log(DEBUG) { "XML Request: #{req_string}" }
- res_string, is_fault = route(req_string, req_charset)
- log(DEBUG) { "XML Response: #{res_string}" }
-
- @response['Cache-Control'] = 'private'
- if req_charset
- @response['content-type'] = "#{@mediatype}; charset=\"#{req_charset}\""
- else
- @response['content-type'] = @mediatype
- end
- if is_fault
+ conn_data = ::SOAP::StreamHandler::ConnectionData.new
+ conn_data.receive_string = @request.dump
+ conn_data.receive_contenttype = @request.contenttype
+ log(DEBUG) { "XML Request: #{conn_data.receive_string}" }
+ conn_data = route(conn_data)
+ log(DEBUG) { "XML Response: #{conn_data.send_string}" }
+ if conn_data.is_fault
@response['Status'] = 500
end
- @response.body = res_string
+ @response['Cache-Control'] = 'private'
+ @response.body = conn_data.send_string
+ @response['content-type'] = conn_data.send_contenttype
rescue Exception
- res_string = create_fault_response($!)
+ conn_data = create_fault_response($!)
@response['Cache-Control'] = 'private'
- @response['content-type'] = @mediatype
@response['Status'] = 500
+ @response.body = conn_data.send_string
+ @response['content-type'] = conn_data.send_contenttype || @mediatype
ensure
buf = ''
@response.send_response(buf)
diff --git a/lib/soap/rpc/driver.rb b/lib/soap/rpc/driver.rb
index dd433ca33f..655174cf33 100644
--- a/lib/soap/rpc/driver.rb
+++ b/lib/soap/rpc/driver.rb
@@ -180,15 +180,21 @@ private
def invoke(headers, body)
set_wiredump_file_base(body.elename.name)
- @proxy.invoke(headers, body)
+ env = @proxy.invoke(headers, body)
+ if env.nil?
+ return nil, nil
+ else
+ return env.header, env.body
+ end
end
def call(name, *params)
set_wiredump_file_base(name)
# Convert parameters: params array => SOAPArray => members array
params = Mapping.obj2soap(params, @mapping_registry).to_a
- header, body = @proxy.call(nil, name, *params)
- raise EmptyResponseError.new("Empty response.") unless body
+ env = @proxy.call(nil, name, *params)
+ raise EmptyResponseError.new("Empty response.") unless env
+ header, body = env.header, env.body
begin
@proxy.check_fault(body)
rescue SOAP::FaultError => e
diff --git a/lib/soap/rpc/element.rb b/lib/soap/rpc/element.rb
index 395823ab00..8a2f319293 100644
--- a/lib/soap/rpc/element.rb
+++ b/lib/soap/rpc/element.rb
@@ -43,7 +43,7 @@ class SOAPBody < SOAPStruct
end
def void?
- root_node.nil? # || root_node.is_a?(SOAPNil)
+ root_node.nil?
end
def fault
@@ -113,6 +113,7 @@ class SOAPMethod < SOAPStruct
params.each do |param, data|
@inparam[param] = data
data.elename.name = param
+ data.parent = self
end
end
@@ -226,6 +227,8 @@ class SOAPMethodResponse < SOAPMethod
def retval=(retval)
@retval = retval
@retval.elename = @retval.elename.dup_name(@retval_name || 'return')
+ retval.parent = self
+ retval
end
def each
diff --git a/lib/soap/rpc/proxy.rb b/lib/soap/rpc/proxy.rb
index 5825a27138..7d9dbe519e 100644
--- a/lib/soap/rpc/proxy.rb
+++ b/lib/soap/rpc/proxy.rb
@@ -12,6 +12,7 @@ require 'soap/mapping'
require 'soap/rpc/rpc'
require 'soap/rpc/element'
require 'soap/streamHandler'
+require 'soap/mimemessage'
module SOAP
@@ -79,7 +80,6 @@ public
raise SOAP::RPC::MethodDefinitionError.new(
"Method: #{ name } not defined.")
end
-
Request.new(method, values)
end
@@ -91,21 +91,30 @@ public
req_body = SOAPBody.new(req_body)
end
opt = create_options
- send_string = Processor.marshal(req_header, req_body, opt)
- data = @streamhandler.send(send_string, soapaction)
- if data.receive_string.empty?
+ opt[:external_content] = nil
+ req_env = SOAPEnvelope.new(req_header, req_body)
+ send_string = Processor.marshal(req_env, opt)
+ conn_data = StreamHandler::ConnectionData.new(send_string)
+ if ext = opt[:external_content]
+ mime = MIMEMessage.new
+ ext.each do |k, v|
+ mime.add_attachment(v.data)
+ end
+ mime.add_part(conn_data.send_string + "\r\n")
+ mime.close
+ conn_data.send_string = mime.content_str
+ conn_data.send_contenttype = mime.headers['content-type'].str
+ end
+ conn_data = @streamhandler.send(conn_data, soapaction)
+ if conn_data.receive_string.empty?
return nil, nil
end
- opt = create_options
- opt[:charset] = @mandatorycharset ||
- StreamHandler.parse_media_type(data.receive_contenttype)
- res_header, res_body = Processor.unmarshal(data.receive_string, opt)
- return res_header, res_body
+ unmarshal(conn_data, opt)
end
def call(headers, name, *values)
req = create_request(name, *values)
- return invoke(headers, req.method, req.method.soapaction || @soapaction)
+ invoke(headers, req.method, req.method.soapaction || @soapaction)
end
def check_fault(body)
@@ -116,6 +125,29 @@ public
private
+ def unmarshal(conn_data, opt)
+ contenttype = conn_data.receive_contenttype
+ if /#{MIMEMessage::MultipartContentType}/i =~ contenttype
+ opt[:external_content] = {}
+ mime = MIMEMessage.parse("Content-Type: " + contenttype,
+ conn_data.receive_string)
+ mime.parts.each do |part|
+ value = Attachment.new(part.content)
+ value.contentid = part.contentid
+ obj = SOAPAttachment.new(value)
+ opt[:external_content][value.contentid] = obj if value.contentid
+ end
+ opt[:charset] = @mandatorycharset ||
+ StreamHandler.parse_media_type(mime.root.headers['content-type'].str)
+ env = Processor.unmarshal(mime.root.content, opt)
+ else
+ opt[:charset] = @mandatorycharset ||
+ ::SOAP::StreamHandler.parse_media_type(contenttype)
+ env = Processor.unmarshal(conn_data.receive_string, opt)
+ end
+ env
+ end
+
def create_header(headers)
header = SOAPHeader.new()
headers.each do |content, mustunderstand, encodingstyle|
diff --git a/lib/soap/rpc/router.rb b/lib/soap/rpc/router.rb
index 527ec05768..12622c72b1 100644
--- a/lib/soap/rpc/router.rb
+++ b/lib/soap/rpc/router.rb
@@ -11,6 +11,8 @@ require 'soap/processor'
require 'soap/mapping'
require 'soap/rpc/rpc'
require 'soap/rpc/element'
+require 'soap/streamHandler'
+require 'soap/mimemessage'
module SOAP
@@ -47,42 +49,96 @@ class Router
end
# Routing...
- def route(soap_string, charset = nil)
- opt = options
- opt[:charset] = charset
- is_fault = false
+ #def route(soap_string, charset = nil)
+ def route(conn_data)
+ soap_response = nil
begin
- header, body = Processor.unmarshal(soap_string, opt)
+ env = unmarshal(conn_data)
+ if env.nil?
+ raise ArgumentError.new("Illegal SOAP marshal format.")
+ end
# So far, header is omitted...
- soap_request = body.request
+ soap_request = env.body.request
unless soap_request.is_a?(SOAPStruct)
raise RPCRoutingError.new("Not an RPC style.")
end
soap_response = dispatch(soap_request)
rescue Exception
soap_response = fault($!)
- is_fault = true
+ conn_data.is_fault = true
end
+ opt = options
+ opt[:external_content] = nil
header = SOAPHeader.new
body = SOAPBody.new(soap_response)
- response_string = Processor.marshal(header, body, opt)
-
- return response_string, is_fault
+ env = SOAPEnvelope.new(header, body)
+ response_string = Processor.marshal(env, opt)
+ conn_data.send_string = response_string
+ if ext = opt[:external_content]
+ mime = MIMEMessage.new
+ ext.each do |k, v|
+ mime.add_attachment(v.data)
+ end
+ mime.add_part(conn_data.send_string + "\r\n")
+ mime.close
+ conn_data.send_string = mime.content_str
+ conn_data.send_contenttype = mime.headers['content-type'].str
+ end
+ conn_data
end
# Create fault response string.
def create_fault_response(e, charset = nil)
header = SOAPHeader.new
- soap_response = fault(e)
- body = SOAPBody.new(soap_response)
+ body = SOAPBody.new(fault(e))
+ env = SOAPEnvelope.new(header, body)
opt = options
+ opt[:external_content] = nil
opt[:charset] = charset
- Processor.marshal(header, body, opt)
+ response_string = Processor.marshal(env, opt)
+ conn_data = StreamHandler::ConnectionData.new(response_string)
+ conn_data.is_fault = true
+ if ext = opt[:external_content]
+ mime = MIMEMessage.new
+ ext.each do |k, v|
+ mime.add_attachment(v.data)
+ end
+ mime.add_part(conn_data.send_string + "\r\n")
+ mime.close
+ conn_data.send_string = mime.content_str
+ conn_data.send_contenttype = mime.headers['content-type'].str
+ end
+ conn_data
end
private
+ def unmarshal(conn_data)
+ opt = options
+ contenttype = conn_data.receive_contenttype
+ if /#{MIMEMessage::MultipartContentType}/i =~ contenttype
+ opt[:external_content] = {}
+ mime = MIMEMessage.parse("Content-Type: " + contenttype,
+ conn_data.receive_string)
+ mime.parts.each do |part|
+ value = Attachment.new(part.content)
+ value.contentid = part.contentid
+ obj = SOAPAttachment.new(value)
+ opt[:external_content][value.contentid] = obj if value.contentid
+ end
+ opt[:charset] =
+ StreamHandler.parse_media_type(mime.root.headers['content-type'].str)
+ env = Processor.unmarshal(mime.root.content, opt)
+ else
+ opt[:charset] = ::SOAP::StreamHandler.parse_media_type(contenttype)
+ env = Processor.unmarshal(conn_data.receive_string, opt)
+ end
+ charset = opt[:charset]
+ conn_data.send_contenttype = "text/xml; charset=\"#{charset}\""
+ env
+ end
+
# Create new response.
def create_response(qname, result)
name = fqname(qname)
diff --git a/lib/soap/rpc/soaplet.rb b/lib/soap/rpc/soaplet.rb
index 4b25c68161..e67593210d 100644
--- a/lib/soap/rpc/soaplet.rb
+++ b/lib/soap/rpc/soaplet.rb
@@ -67,26 +67,26 @@ public
def do_POST(req, res)
namespace = parse_soapaction(req.meta_vars['HTTP_SOAPACTION'])
router = lookup_router(namespace)
-
- is_fault = false
-
- charset = ::SOAP::StreamHandler.parse_media_type(req['content-type'])
begin
- response_stream, is_fault = router.route(req.body, charset)
+ 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)
+ if conn_data.is_fault
+ res.status = WEBrick::HTTPStatus::RC_INTERNAL_SERVER_ERROR
+ end
+ res.body = conn_data.send_string
+ res['content-type'] = conn_data.send_contenttype
rescue Exception => e
- response_stream = router.create_fault_response(e)
- is_fault = true
+ 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
- res.body = response_stream
- res['content-type'] = "text/xml; charset=\"#{charset}\""
- if response_stream.is_a?(IO)
+ if res.body.is_a?(IO)
res.chunked = true
end
-
- if is_fault
- res.status = WEBrick::HTTPStatus::RC_INTERNAL_SERVER_ERROR
- end
end
private