Class: XMLRPC::Client

Inherits:
Object
  • Object
show all
Includes:
ParseContentType, ParserWriterChooseMixin
Defined in:
lib/xmlrpc/client.rb

Overview

Provides remote procedure calls to a XML-RPC server.

After setting the connection-parameters with XMLRPC::Client.new which creates a new XMLRPC::Client instance, you can execute a remote procedure by sending the XMLRPC::Client#call or XMLRPC::Client#call2 message to this new instance.

The given parameters indicate which method to call on the remote-side and of course the parameters for the remote procedure.

require "xmlrpc/client"

server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80)
begin
  param = server.call("michael.add", 4, 5)
  puts "4 + 5 = #{param}"
rescue XMLRPC::FaultException => e
  puts "Error:"
  puts e.faultCode
  puts e.faultString
end

or

require "xmlrpc/client"

server = XMLRPC::Client.new("www.ruby-lang.org", "/RPC2", 80)
ok, param = server.call2("michael.add", 4, 5)
if ok then
  puts "4 + 5 = #{param}"
else
  puts "Error:"
  puts param.faultCode
  puts param.faultString
end

Defined Under Namespace

Classes: Proxy

Constant Summary collapse

USER_AGENT =
"XMLRPC::Client (Ruby #{RUBY_VERSION})"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ParseContentType

#parse_content_type

Methods included from ParserWriterChooseMixin

#set_parser, #set_writer

Constructor Details

#initialize(host = nil, path = nil, port = nil, proxy_host = nil, proxy_port = nil, user = nil, password = nil, use_ssl = nil, timeout = nil) ⇒ Client

Creates an object which represents the remote XML-RPC server on the given host. If the server is CGI-based, path is the path to the CGI-script, which will be called, otherwise (in the case of a standalone server) path should be "/RPC2". port is the port on which the XML-RPC server listens.

If proxy_host is given, then a proxy server listening at proxy_host is used. proxy_port is the port of the proxy server.

Default values for host, path and port are ‘localhost’, ‘/RPC2’ and ‘80’ respectively using SSL ‘443’.

If user and password are given, each time a request is sent, an Authorization header is sent. Currently only Basic Authentication is implemented, no Digest.

If use_ssl is set to true, communication over SSL is enabled.

Note, that you need the SSL package from RAA installed.

Parameter timeout is the time to wait for a XML-RPC response, defaults to 30.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/xmlrpc/client.rb', line 83

def initialize(host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil,
               user=nil, password=nil, use_ssl=nil, timeout=nil)

  @http_header_extra = nil
  @http_last_response = nil
  @cookie = nil

  @host       = host || "localhost"
  @path       = path || "/RPC2"
  @proxy_host = proxy_host
  @proxy_port = proxy_port
  @proxy_host ||= 'localhost' if @proxy_port != nil
  @proxy_port ||= 8080 if @proxy_host != nil
  @use_ssl    = use_ssl || false
  @timeout    = timeout || 30

  if use_ssl
    require "net/https"
    @port = port || 443
  else
    @port = port || 80
  end

  @user, @password = user, password

  set_auth

  # convert ports to integers
  @port = @port.to_i if @port != nil
  @proxy_port = @proxy_port.to_i if @proxy_port != nil

  # HTTP object for synchronous calls
  @http = net_http(@host, @port, @proxy_host, @proxy_port)
  @http.use_ssl = @use_ssl if @use_ssl
  @http.read_timeout = @timeout
  @http.open_timeout = @timeout

  @parser = nil
  @create = nil
end

Instance Attribute Details

Get and set the HTTP Cookie header.



205
206
207
# File 'lib/xmlrpc/client.rb', line 205

def cookie
  @cookie
end

#httpObject (readonly)

Returns the Net::HTTP object for the client. If you want to change HTTP client options except header, cookie, timeout, user and password, use Net::HTTP directly.

Since 2.1.0.



196
197
198
# File 'lib/xmlrpc/client.rb', line 196

def http
  @http
end

#http_header_extraObject

Add additional HTTP headers to the request



199
200
201
# File 'lib/xmlrpc/client.rb', line 199

def http_header_extra
  @http_header_extra
end

#http_last_responseObject (readonly)

Returns the Net::HTTPResponse object of the last RPC.



202
203
204
# File 'lib/xmlrpc/client.rb', line 202

def http_last_response
  @http_last_response
end

#passwordObject

Return the corresponding attributes.



209
210
211
# File 'lib/xmlrpc/client.rb', line 209

def password
  @password
end

#timeoutObject

Return the corresponding attributes.



209
210
211
# File 'lib/xmlrpc/client.rb', line 209

def timeout
  @timeout
end

#userObject

Return the corresponding attributes.



209
210
211
# File 'lib/xmlrpc/client.rb', line 209

def user
  @user
end

Class Method Details

.new2(uri, proxy = nil, timeout = nil) ⇒ Object Also known as: new_from_uri

Creates an object which represents the remote XML-RPC server at the given uri. The URI should have a host, port, path, user and password. Example: user:password@host:port/path

Raises an ArgumentError if the uri is invalid, or if the protocol isn’t http or https.

If a proxy is given it should be in the form of “host:port”.

The optional timeout defaults to 30 seconds.



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/xmlrpc/client.rb', line 137

def new2(uri, proxy=nil, timeout=nil)
  begin
    url = URI(uri)
  rescue URI::InvalidURIError => e
    raise ArgumentError, e.message, e.backtrace
  end

  unless URI::HTTP === url
    raise ArgumentError, "Wrong protocol specified. Only http or https allowed!"
  end

  proto  = url.scheme
  user   = url.user
  passwd = url.password
  host   = url.host
  port   = url.port
  path   = url.path.empty? ? nil : url.request_uri

  proxy_host, proxy_port = (proxy || "").split(":")
  proxy_port = proxy_port.to_i if proxy_port

  self.new(host, path, port, proxy_host, proxy_port, user, passwd, (proto == "https"), timeout)
end

.new3(hash = {}) ⇒ Object Also known as: new_from_hash

Receives a Hash and calls XMLRPC::Client.new with the corresponding values.

The hash parameter has following case-insensitive keys:

  • host

  • path

  • port

  • proxy_host

  • proxy_port

  • user

  • password

  • use_ssl

  • timeout



176
177
178
179
180
181
182
183
184
# File 'lib/xmlrpc/client.rb', line 176

def new3(hash={})

  # convert all keys into lowercase strings
  h = {}
  hash.each { |k,v| h[k.to_s.downcase] = v }

  self.new(h['host'], h['path'], h['port'], h['proxy_host'], h['proxy_port'], h['user'], h['password'],
           h['use_ssl'], h['timeout'])
end

Instance Method Details

#call(method, *args) ⇒ Object

Invokes the method named method with the parameters given by args on the XML-RPC server.

The method parameter is converted into a String and should be a valid XML-RPC method-name.

Each parameter of args must be of one of the following types, where Hash, Struct and Array can contain any of these listed types:

  • Fixnum, Bignum

  • TrueClass, FalseClass, true, false

  • String, Symbol

  • Float

  • Hash, Struct

  • Array

  • Date, Time, XMLRPC::DateTime

  • XMLRPC::Base64

  • A Ruby object which class includes XMLRPC::Marshallable (only if Config::ENABLE_MARSHALLABLE is true). That object is converted into a hash, with one additional key/value pair _class___ which contains the class name for restoring that object later.

The method returns the return-value from the Remote Procedure Call.

The type of the return-value is one of the types shown above.

A Bignum is only allowed when it fits in 32-bit. A XML-RPC dateTime.iso8601 type is always returned as a XMLRPC::DateTime object. Struct is never returned, only a Hash, the same for a Symbol, where as a String is always returned. XMLRPC::Base64 is returned as a String from xmlrpc4r version 1.6.1 on.

If the remote procedure returned a fault-structure, then a XMLRPC::FaultException exception is raised, which has two accessor-methods faultCode an Integer, and faultString a String.



268
269
270
271
272
273
274
275
# File 'lib/xmlrpc/client.rb', line 268

def call(method, *args)
  ok, param = call2(method, *args)
  if ok
    param
  else
    raise param
  end
end

#call2(method, *args) ⇒ Object

The difference between this method and XMLRPC::Client#call is, that this method will NOT raise a XMLRPC::FaultException exception.

The method returns an array of two values. The first value indicates if the second value is true or an XMLRPC::FaultException.

Both are explained in XMLRPC::Client#call.

Simple to remember: The “2” in “call2” denotes the number of values it returns.



286
287
288
289
290
# File 'lib/xmlrpc/client.rb', line 286

def call2(method, *args)
  request = create().methodCall(method, *args)
  data = do_rpc(request, false)
  parser().parseMethodResponse(data)
end

#call2_async(method, *args) ⇒ Object

Same as XMLRPC::Client#call2, but can be called concurrently.

See also XMLRPC::Client#call_async



320
321
322
323
324
# File 'lib/xmlrpc/client.rb', line 320

def call2_async(method, *args)
  request = create().methodCall(method, *args)
  data = do_rpc(request, true)
  parser().parseMethodResponse(data)
end

#call_async(method, *args) ⇒ Object

Similar to XMLRPC::Client#call, however can be called concurrently and use a new connection for each request. In contrast to the corresponding method without the _async suffix, which use connect-alive (one connection for all requests).

Note, that you have to use Thread to call these methods concurrently. The following example calls two methods concurrently:

Thread.new {
  p client.call_async("michael.add", 4, 5)
}

Thread.new {
  p client.call_async("michael.div", 7, 9)
}


308
309
310
311
312
313
314
315
# File 'lib/xmlrpc/client.rb', line 308

def call_async(method, *args)
  ok, param = call2_async(method, *args)
  if ok
    param
  else
    raise param
  end
end

#multicall(*methods) ⇒ Object

You can use this method to execute several methods on a XMLRPC server which support the multi-call extension.

s.multicall(
  ['michael.add', 3, 4],
  ['michael.sub', 4, 5]
)
# => [7, -1]


335
336
337
338
339
340
341
342
# File 'lib/xmlrpc/client.rb', line 335

def multicall(*methods)
  ok, params = multicall2(*methods)
  if ok
    params
  else
    raise params
  end
end

#multicall2(*methods) ⇒ Object

Same as XMLRPC::Client#multicall, but returns two parameters instead of raising an XMLRPC::FaultException.

See XMLRPC::Client#call2



348
349
350
# File 'lib/xmlrpc/client.rb', line 348

def multicall2(*methods)
  gen_multicall(methods, false)
end

#multicall2_async(*methods) ⇒ Object

Same as XMLRPC::Client#multicall2, but can be called concurrently.

See also XMLRPC::Client#multicall_async



380
381
382
# File 'lib/xmlrpc/client.rb', line 380

def multicall2_async(*methods)
  gen_multicall(methods, true)
end

#multicall_async(*methods) ⇒ Object

Similar to XMLRPC::Client#multicall, however can be called concurrently and use a new connection for each request. In contrast to the corresponding method without the _async suffix, which use connect-alive (one connection for all requests).

Note, that you have to use Thread to call these methods concurrently. The following example calls two methods concurrently:

Thread.new {
  p client.multicall_async("michael.add", 4, 5)
}

Thread.new {
  p client.multicall_async("michael.div", 7, 9)
}


368
369
370
371
372
373
374
375
# File 'lib/xmlrpc/client.rb', line 368

def multicall_async(*methods)
  ok, params = multicall2_async(*methods)
  if ok
    params
  else
    raise params
  end
end

#proxy(prefix = nil, *args) ⇒ Object

Returns an object of class XMLRPC::Client::Proxy, initialized with prefix and args.

A proxy object returned by this method behaves like XMLRPC::Client#call, i.e. a call on that object will raise a XMLRPC::FaultException when a fault-structure is returned by that call.



391
392
393
# File 'lib/xmlrpc/client.rb', line 391

def proxy(prefix=nil, *args)
  Proxy.new(self, prefix, args, :call)
end

#proxy2(prefix = nil, *args) ⇒ Object

Almost the same like XMLRPC::Client#proxy only that a call on the returned XMLRPC::Client::Proxy object will return two parameters.

See XMLRPC::Client#call2



399
400
401
# File 'lib/xmlrpc/client.rb', line 399

def proxy2(prefix=nil, *args)
  Proxy.new(self, prefix, args, :call2)
end

#proxy2_async(prefix = nil, *args) ⇒ Object

Same as XMLRPC::Client#proxy2, but can be called concurrently.

See also XMLRPC::Client#proxy_async



426
427
428
# File 'lib/xmlrpc/client.rb', line 426

def proxy2_async(prefix=nil, *args)
  Proxy.new(self, prefix, args, :call2_async)
end

#proxy_async(prefix = nil, *args) ⇒ Object

Similar to XMLRPC::Client#proxy, however can be called concurrently and use a new connection for each request. In contrast to the corresponding method without the _async suffix, which use connect-alive (one connection for all requests).

Note, that you have to use Thread to call these methods concurrently. The following example calls two methods concurrently:

Thread.new {
  p client.proxy_async("michael.add", 4, 5)
}

Thread.new {
  p client.proxy_async("michael.div", 7, 9)
}


419
420
421
# File 'lib/xmlrpc/client.rb', line 419

def proxy_async(prefix=nil, *args)
  Proxy.new(self, prefix, args, :call_async)
end