-
Notifications
You must be signed in to change notification settings - Fork 2
XMLRPC
Your crails server may act as an XMLRPC server using the crails-xmlrpc
module.
To install the module, run the following command on your crails project:
crails module xmlrpc install
Your xmlrpc server will be implemented as a crails' controller. You will need to create a class that inherits from XmlRpc::Controller
:
#ifndef MY_XMLRPC_CONTROLLER_HPP
# define MY_XMLRPC_CONTROLLER_HPP
# include <crails/xmlrpc/controller.hpp>
class MyXmlrpcController : public XmlRpc::Controller
{
public:
MyXmlrpcController(Crails::Params& params) : XmlRpc::Controller(params)
{
}
};
#endif
Everything is ready for you to implement your XMLRPC-based API. Firstly, you may declare your methods within the MyXmlrpcController
class. Then, you will register those methods in the class' constructor.
class MyXmlrpcController : public XmlRpc::Controller
{
public:
MyXmlrpcController(Crails::Params& params) : XmlRpc::Controller(params)
{
register_method("make_addition", &MyXmlrpcController::make_addition);
}
void make_addition(int p1, int p2)
{
respond_with(p1 + p2); // sets the xmlrpc return value
}
};
Your function parameters will be automatically filled with those provided in the XMLRPC request. Complex types such as struct
and array
are also supported, see the XMLRPC Types section for more details.
Lastly, you will have to connect the crails router to your XMLRPC controller. To do that, you need to create a route that redirects to the endpoint
method of your controller.
void Router::initialize()
{
SetRoute("POST", "/my_xmlrpc_endpoint", MyXmlrpcController, endpoint);
}
The endpoint
method is implemented in the XmlRpc::Controller
, and will dispatch the request to a matching registered method (or respond with a fault response if no matching method has been found).
You may also implement an xmlrpc client, using XmlRpc::Client
.
#include <crails/xmlrpc/client.hpp>
#include <crails/xmlrpc/fault.hpp>
try
{
XmlRpc::Client client("http://localhost:3000/xmlrpc_endpoint");
int result = client.call("make_addition", 12, 42);
std::cout << "call result: " << result << std::endl;
}
catch (const XmlRpc::Fault& fault)
{
std::cout << "XmlRpc::Fault: (" << fault.fault_code() << ") " << fault.what() << std::endl;
}
Note that XmlRpc::Client::call
returns an object of type XmlRpc::Variable
, which can cast to any xmlrpc supported type.
The XmlRpc::Variable
type is a container that can cast to any type supported by the xmlrpc protocol.
You may implement struct
objects by inheriting from the XmlRpc::Struct
class.
#include <crails/xmlrpc/struct.hpp>
struct MyStruct : public XmlRpc::Struct
{
// You must provide a constructor taking `XmlRpc::Variable` as parameter
MyStruct(const XmlRpc::Variable& data) : Struct(data) {}
// You must also provide a constructor that takes no parameters
MyStruct() {}
// The following macros allow you to declare your struct's properties
XmlRpc_int_property(id)
XmlRpc_string_property(name)
XmlRpc_double_property(ratio)
XmlRpc_bool_property(deleted)
XmlRpc_date_property(created_at)
XmlRpc_date_property(updated_at)
XmlRpc_string_array_property(surnames) // append array to the type to create a property based
};
The XmlRpc_[type]_property
macros will generate getter and setters for the given properties.
Note that the XmlRpc_[type]_array_property
macro uses std::vector
to implement the array property.
A struct
can be a member within another struct
. In such a case, you need to declare both struct
types as inheriting XmlRpc::Struct
, and initialize the nested struct
in the nesting struct
constructor.
// Defining the type for the struct that will be nested
struct NestedStruct : public XmlRpc::Struct
{
NestedStruct(const XmlRpc::Variable& data) : XmlRpc::Struct(data) {}
NestedStruct() {}
XmlRpc_int_property(id)
XmlRpc_string_property(name)
};
// Defining the type for the struct that will contain NestedStruct
struct MyStruct : public XmlRpc::Struct
{
NestedStruct nested_struct;
MyStruct(const XmlRpc::Variable& data) :
XmlRpc::Struct(data),
nested_struct(data["nested_struct"]) // data["nested_struct"] will return the `XmlRpc::Variable` object
{} // for the "nested_struct" member of MyStruct.
MyStruct();
XmlRpc_int_property(id)
};
TODO: Array support in crails-xmlrpc is still partial.
Arrays are implemented through the std::vector
container. Vectors can be passed and used as parameters transparently, as long as the contained type is supported (any of the native type, or a type inheriting from XmlRpc::Struct).
Dates are implemented using the std::time_t
type.