Quick Start
Lets start with simple example that will demonstrate basic XML-RPC client. This client example designed to be compatible with server example.
#include <iostream> #include <libiqxmlrpc/libiqxmlrpc.h> #include <libiqxmlrpc/client.h> #include <libiqxmlrpc/http_client.h> int main() { using namespace iqxmlrpc; // 1: Create a client object Client<Http_client_connection> client(iqnet::Inet_addr(3344)); // 2: Fill method parameters Param_list pl; pl.push_back(Struct()); pl[0].insert("var1", 1); pl[0].insert("var2", "value"); // 3: Call a remote method Response r = client.execute("echo", pl); // 4: Process method output assert(r.value()["var1"].get_int() == 1); assert(r.value()["var2"].get_string() == "value"); }
Comments with figures state different phases of a process of writing client code with Libiqxmlrpc. Here they are:
- Create and configure client object
- Make remote invocations
- Construct a set of parameters
- Call a remote method
- Treat method output
A following sections say more about those phases.
Setting Up a Client
An abstract base class iqxmlrpc::Client_base provides interface for client configuration and execution of remote methods. In summary, this interface allows one to:
- Configure client connections:
- Specify Proxy Settings
- Specify Connection Timeout
- Specify Keep-alive Flag
- Manage Client Authorization
- Method Execution
Create Client
However, the first thing a developer need, is to create an instance of Client_base. Concrete sub-classes of Client_base take care of a transport used to communicate remote service. There is template class iqxmlrpc::Client<TRANSPORT> that should be used for instantiating Client_base children. User must specify appropriate TRANSPORT parameter for his situation, depending on transport required (HTTP or HTTPS).
Possible options are:
- iqxmlrpc::Http_client_connection {idx: iqxmlrpc::Http_client_connection }
- iqxmlrpc::Https_client_connection {idx: iqxmlrpc::Https_client_connection }
In a common case client creation code will look like a following:
iqxmlrpc::Client<TRANSPORT> client( iqnet::Inet_addr(host, port), "/RPC2" );
An /RPC2 string is an URI that can be configured by a owner of a remote service.
One can fearlessly substitute TRANSPORT template argument with Http_client_connection in an example above. However, enabling HTTPS needs some additional magic from a developer. I.e. one must initialize SSL subsystem before creating any SSL connection:
#include <libiqxmlrpc/libiqxmlrpc.h> #include <libiqxmlrpc/https_client.h> using namespace iqxmlrpc; Client_base* create_https_client(iqnet::Inet_addr addr, const std::string& uri) { // Initialize SSL subsystem iqnet::ssl::ctx = iqnet::ssl::Ctx::client_only(); return new Client<Https_client_connection>(addr, uri); }
Configure Client Connections
Specify Proxy Settings
- Client_base::set_proxy
- This method allows one set an HTTP proxy host for all client's outgoing connections.
Client<Http_client_connection> client(Inet_addr("host.com", 8080)); client.set_proxy(Inet_addr("my.proxy.com", 80));
Specify Connection Timeout
- Client_base::set_timeout
- This method sets connection timeout in seconds. A negative value means no timeout. Library throws iqxmlrpc::Client_timeout exception during processing remote call in case when time is out.
void timed_call(Client_base& client, int timeout) { client.set_timeout(timeout); try { Response r = client.execute("foo", Value()); // work with r ... } catch(const Client_timeout&) { // handle connection timeout } }
Note that timeout specified with set_timeout method does not affect connecting process.
Specify Keep-alive Flag
- Client_base::set_keep_alive
- This method manages HTTP keep-alive facility on a client connection. If one enables this flag and remote server supports this facility then all subsequent method execution request will go through the same open connection.
void banch_of_requests(Client_base& client) { // Ask server to not close connection after response client.set_keep_alive(true); client.execute("foo", Value()); // Hope, the same connection. // Depending on server implementation. client.execute("bar", Value()); }
Manage Client Authorization
- Client_base::set_authinfo
- This method sets user/password pair to pass through HTTP authentication mechanism.
client.set_authinfo("admin", "12345");
Note that though library allows use set_authinfo with plain a HTTP connections, one should not rely on it because in this case your credential information may become available to traffic sniffers.
Method Execution
Calling Remote Method
XML-RPC standard allows transfer a number of input parameters to a remote procedure. Actually, quite often XML-RPC APIs take in account only first of them, and require transferring parameters in a key-value form. Just because this method is much more convenient and reflects to a dynamic nature of XML-RPC it-self.
Library provides comfortable way for both approaches. The iqxmlrpc::Client provides two overloaded interface for calling remote methods:
namespace iqxmlrpc { typedef std::vector<Value> Param_list; class Client { public: // ... Response execute( const std::string& method, const Param_list& ); Response execute( const std::string& method, const Value& ); }; } // namespace iqxmlrpc
Both methods accept name of calling method as a first parameter. A former allows transfer an array of input parameters (as the standard suggests).
A second one puts specified value into first element of array of parameters and just calls a first one.
Deal with Method Responses
An XML-RPC response may be of two types: method output, and failure report. Objects of iqxmlrpc::Response class serve a destination for result of a remote call and may hold either type of response.
A Response::value method gives user access to a received result. And Response::is_fault allows user check if received XML-RPC packet contained failure notice. If user try access response value with value method and an object is actually containing an XML-RPC failure notice then exception that contain all information about failure would be thrown. This behavior gives user ability write a code in optimistic manner.
Response::fault_code and Response::fault_string methods gives an alternative way to retrieve information about failure.
Please note that Response objects may contain only XML-RPC failures. Failures form a network layer or some HTTP issues are always exceptions.
std::string get_name_of_object(Client_base& client, int object_id) { try { Response r = client("get_object_name", object_id); return r.value().get_string(); } catch (const Client_timeout&) { std::cerr << "Timeout" << std::endl; exit(1); } catch (const Exception& e) { std::cerr << "XML-RPC error " << e.code() << ": " << e.what() << std::endl; exit(2); } }





