-
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 installYour 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)
{
}
};
#endifEverything 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.