diff options
author | Leon Breedt <bitserf@gmail.com> | 2005-02-25 23:39:39 +0000 |
---|---|---|
committer | Leon Breedt <bitserf@gmail.com> | 2005-02-25 23:39:39 +0000 |
commit | 6f5a7b200443baf209d2f33c428ed4a4059782f7 (patch) | |
tree | 9c3942fe27be69c102873d9fdaa13f66dc12853d /actionwebservice/lib/action_web_service/vendor/ws/encoding | |
parent | 10faf204b712763f05a2b3155a4fd9c5338f1fb2 (diff) | |
download | rails-6f5a7b200443baf209d2f33c428ed4a4059782f7.tar.gz rails-6f5a7b200443baf209d2f33c428ed4a4059782f7.tar.bz2 rails-6f5a7b200443baf209d2f33c428ed4a4059782f7.zip |
merged the changes for the upcoming 0.6.0:
seperate out protocol marshaling into a small 'ws' library in vendor, so that
AWS itself only does integration with ActionPack, and so we can keep protocol
specific code in AWS proper to a minimum. refactor unit tests to get 95%
code coverage (for a baseline).
be far more relaxed about the types given to us by the remote side, don't do
any poor man's type checking, just try to cast and marshal to the correct types if
possible, and if not, return what they gave us anyway. this should make interoperating
with fuzzy XML-RPC clients easier.
if exception reporting is turned on, do best-effort error responses, so that
we can avoid "Internal protocol error" with no details if there is a bug in
AWS itself.
also perform extensive cleanups on AWS proper.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@800 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionwebservice/lib/action_web_service/vendor/ws/encoding')
3 files changed, 169 insertions, 0 deletions
diff --git a/actionwebservice/lib/action_web_service/vendor/ws/encoding/abstract.rb b/actionwebservice/lib/action_web_service/vendor/ws/encoding/abstract.rb new file mode 100644 index 0000000000..257c7d0993 --- /dev/null +++ b/actionwebservice/lib/action_web_service/vendor/ws/encoding/abstract.rb @@ -0,0 +1,26 @@ +module WS + module Encoding + # Encoders operate on _foreign_ objects. That is, Ruby object + # instances that are the _marshaling format specific_ representation + # of objects. In other words, objects that have not yet been marshaled, but + # are in protocol-specific form (such as an AST or DOM element), and not + # native Ruby form. + class AbstractEncoding + def encode_rpc_call(method_name, params) + raise NotImplementedError + end + + def decode_rpc_call(obj) + raise NotImplementedError + end + + def encode_rpc_response(method_name, return_value) + raise NotImplementedError + end + + def decode_rpc_response(obj) + raise NotImplementedError + end + end + end +end diff --git a/actionwebservice/lib/action_web_service/vendor/ws/encoding/soap_rpc_encoding.rb b/actionwebservice/lib/action_web_service/vendor/ws/encoding/soap_rpc_encoding.rb new file mode 100644 index 0000000000..f4d2f5a7d6 --- /dev/null +++ b/actionwebservice/lib/action_web_service/vendor/ws/encoding/soap_rpc_encoding.rb @@ -0,0 +1,90 @@ +require 'soap/processor' +require 'soap/mapping' +require 'soap/rpc/element' + +module WS + module Encoding + class SoapRpcError < WSError + end + + class SoapRpcEncoding < AbstractEncoding + attr_accessor :method_namespace + + def initialize(method_namespace='') + @method_namespace = method_namespace + end + + def encode_rpc_call(method_name, foreign_params) + qname = create_method_qname(method_name) + param_def = [] + params = foreign_params.map do |p| + param_def << ['in', p.param.info.name, p.param.info.data.mapping] + [p.param.info.name, p.soap_object] + end + request = SOAP::RPC::SOAPMethodRequest.new(qname, param_def) + request.set_param(params) + envelope = create_soap_envelope(request) + SOAP::Processor.marshal(envelope) + end + + def decode_rpc_call(obj) + envelope = SOAP::Processor.unmarshal(obj) + unless envelope + raise(SoapRpcError, "Malformed SOAP request") + end + request = envelope.body.request + method_name = request.elename.name + params = request.collect do |key, value| + info = ParamInfo.new(key, nil, nil) + param = Param.new(nil, info) + Marshaling::SoapForeignObject.new(param, request[key]) + end + [method_name, params] + end + + def encode_rpc_response(method_name, return_value) + response = nil + qname = create_method_qname(method_name) + if return_value.nil? + response = SOAP::RPC::SOAPMethodResponse.new(qname, nil) + else + param = return_value.param + soap_object = return_value.soap_object + param_def = [['retval', 'return', param.info.data.mapping]] + if soap_object.is_a?(SOAP::SOAPFault) + response = soap_object + else + response = SOAP::RPC::SOAPMethodResponse.new(qname, param_def) + response.retval = soap_object + end + end + envelope = create_soap_envelope(response) + SOAP::Processor.marshal(envelope) + end + + def decode_rpc_response(obj) + envelope = SOAP::Processor.unmarshal(obj) + unless envelope + raise(SoapRpcError, "Malformed SOAP response") + end + method_name = envelope.body.request.elename.name + return_value = envelope.body.response + info = ParamInfo.new('return', nil, nil) + param = Param.new(nil, info) + return_value = Marshaling::SoapForeignObject.new(param, return_value) + [method_name, return_value] + end + + private + def create_soap_envelope(body) + header = SOAP::SOAPHeader.new + body = SOAP::SOAPBody.new(body) + SOAP::SOAPEnvelope.new(header, body) + end + + def create_method_qname(method_name) + XSD::QName.new(@method_namespace, method_name) + end + end + end +end diff --git a/actionwebservice/lib/action_web_service/vendor/ws/encoding/xmlrpc_encoding.rb b/actionwebservice/lib/action_web_service/vendor/ws/encoding/xmlrpc_encoding.rb new file mode 100644 index 0000000000..b38ae81abf --- /dev/null +++ b/actionwebservice/lib/action_web_service/vendor/ws/encoding/xmlrpc_encoding.rb @@ -0,0 +1,53 @@ +require 'xmlrpc/marshal' + +module WS + module Encoding + class XmlRpcError < WSError + end + + class XmlRpcEncoding < AbstractEncoding + def encode_rpc_call(method_name, params) + XMLRPC::Marshal.dump_call(method_name, *params) + end + + def decode_rpc_call(obj) + method_name, params = XMLRPC::Marshal.load_call(obj) rescue nil + unless method_name && params + raise(XmlRpcError, "Malformed XML-RPC request") + end + i = 0 + params = params.map do |value| + param = XmlRpcDecodedParam.new("param#{i}", value) + i += 1 + param + end + [method_name, params] + end + + def encode_rpc_response(method_name, return_value) + if return_value.nil? + XMLRPC::Marshal.dump_response(true) + else + XMLRPC::Marshal.dump_response(return_value) + end + end + + def decode_rpc_response(obj) + return_value = XMLRPC::Marshal.load_response(obj) rescue nil + if return_value.nil? + raise(XmlRpcError, "Malformed XML-RPC response") + end + [nil, XmlRpcDecodedParam.new('return', return_value)] + end + end + + class XmlRpcDecodedParam + attr :param + + def initialize(name, value) + info = ParamInfo.new(name, value.class) + @param = Param.new(value, info) + end + end + end +end |