mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
100015cd80
namespace as a default, fixes SOAP marshaling for .NET, a regression since the merge. Make array annotation be recursive in WS::Marshaling::SoapMarshaling, this makes typed arrays buried in nested structures still be annotated correctly. Support :layered dispatching mode for XML-RPC namespaced method names. Change WS::ParamInfo.create signature to require type_binding, and update all uses of this. Restore #default_api_method functionality, fixes a regression since the merge. Fix marshalling of ActiveRecord::Base derivatives, fixes a regression since the merge. This changeset closes #676, #677, and #678. git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@811 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
82 lines
3.2 KiB
Ruby
82 lines
3.2 KiB
Ruby
require 'uri'
|
|
require 'xmlrpc/client'
|
|
|
|
module ActionWebService # :nodoc:
|
|
module Client # :nodoc:
|
|
|
|
# Implements XML-RPC client support
|
|
#
|
|
# ==== Example Usage
|
|
#
|
|
# class BloggerAPI < ActionWebService::API::Base
|
|
# inflect_names false
|
|
# api_method :getRecentPosts, :returns => [[Blog::Post]]
|
|
# end
|
|
#
|
|
# blog = ActionWebService::Client::XmlRpc.new(BloggerAPI, "http://.../RPC", :handler_name => "blogger")
|
|
# posts = blog.getRecentPosts
|
|
class XmlRpc < Base
|
|
|
|
# Creates a new web service client using the XML-RPC protocol.
|
|
#
|
|
# +api+ must be an ActionWebService::API::Base derivative, and
|
|
# +endpoint_uri+ must point at the relevant URL to which protocol requests
|
|
# will be sent with HTTP POST.
|
|
#
|
|
# Valid options:
|
|
# [<tt>:handler_name</tt>] If the remote server defines its services inside special
|
|
# handler (the Blogger API uses a <tt>"blogger"</tt> handler name for example),
|
|
# provide it here, or your method calls will fail
|
|
def initialize(api, endpoint_uri, options={})
|
|
@api = api
|
|
@handler_name = options[:handler_name]
|
|
@client = XMLRPC::Client.new2(endpoint_uri, options[:proxy], options[:timeout])
|
|
@marshaler = WS::Marshaling::XmlRpcMarshaler.new
|
|
end
|
|
|
|
protected
|
|
def perform_invocation(method_name, args)
|
|
args = transform_outgoing_method_params(method_name, args)
|
|
ok, return_value = @client.call2(public_name(method_name), *args)
|
|
return transform_return_value(method_name, return_value) if ok
|
|
raise(ClientError, "#{return_value.faultCode}: #{return_value.faultString}")
|
|
end
|
|
|
|
def transform_outgoing_method_params(method_name, params)
|
|
info = @api.api_methods[method_name.to_sym]
|
|
expects = info[:expects]
|
|
expects_length = expects.nil?? 0 : expects.length
|
|
if expects_length != params.length
|
|
raise(ClientError, "API declares #{public_name(method_name)} to accept " +
|
|
"#{expects_length} parameters, but #{params.length} parameters " +
|
|
"were supplied")
|
|
end
|
|
params = params.dup
|
|
if expects_length > 0
|
|
i = 0
|
|
expects.each do |spec|
|
|
type_binding = @marshaler.register_type(spec)
|
|
info = WS::ParamInfo.create(spec, type_binding, i)
|
|
params[i] = @marshaler.marshal(WS::Param.new(params[i], info))
|
|
i += 1
|
|
end
|
|
end
|
|
params
|
|
end
|
|
|
|
def transform_return_value(method_name, return_value)
|
|
info = @api.api_methods[method_name.to_sym]
|
|
return true unless returns = info[:returns]
|
|
type_binding = @marshaler.register_type(returns[0])
|
|
info = WS::ParamInfo.create(returns[0], type_binding, 0)
|
|
info.name = 'return'
|
|
@marshaler.transform_inbound(WS::Param.new(return_value, info))
|
|
end
|
|
|
|
def public_name(method_name)
|
|
public_name = @api.public_api_method_name(method_name)
|
|
@handler_name ? "#{@handler_name}.#{public_name}" : public_name
|
|
end
|
|
end
|
|
end
|
|
end
|