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.

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



82
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
# File 'lib/xmlrpc/client.rb', line 82

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.



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

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.



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

def http
  @http
end

#http_header_extraObject

Add additional HTTP headers to the request



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

def http_header_extra
  @http_header_extra
end

#http_last_responseObject (readonly)

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



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

def http_last_response
  @http_last_response
end

#passwordObject

Return the corresponding attributes.



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

def password
  @password
end

#timeoutObject

Return the corresponding attributes.



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

def timeout
  @timeout
end

#userObject

Return the corresponding attributes.



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

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.



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

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



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

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:

  • Integer

  • 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_MARSHALLING 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.

An Integer 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.



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

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.



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

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



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

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)
}


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

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]


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

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



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

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



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

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)
}


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

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.



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

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



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

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



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

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)
}


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

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