Example of XML-RPC Server and Client
Server
In order to run an XMLRPC server, you have to start the HTTP server and install a handler. "/RPC2" is the default URL for XMLRPC. The code contains the xmlRpcHandler, a method handler and a separate test method.
#uses "CtrlHTTP"
#uses "CtrlXmlRp
#uses "xmlrpcHandlerCommon.ctl"
#uses "CtrlZlib"
int HTTP_PORT = 80;
const int HTTPS_PORT = 0; // To enable https, set this to 443
main()
{
//Start the HTTP Server
if (httpServer(false, HTTP_PORT, HTTPS_PORT) < 0)
{
DebugN("ERROR: HTTP-server can't start. --- Check license");
return;
}
//Start the XmlRpc Handler
httpConnect("xmlrpcHandler", "/RPC2");
}
mixed xmlrpcHandler(const mixed content, string user, string ip, dyn_string ds1, dyn_string ds2, int connIdx)
{
string sMethod, sRet;
dyn_mixed daArgs;
mixed methodResult;
mixed xmlResult;
string cookie = httpGetHeader(connIdx, "Cookie");
int ret;
dyn_errClass derr;
//Decode content
ret = xmlrpcDecodeRequest(content, sMethod, daArgs);
derr = getLastError();
if (ret < 0 || dynlen(derr)>=1)
{
throwError(derr);
//Output Error
derr = xmlRpcMakeError(PRIO_SEVERE, ERR_SYSTEM, ERR_PARAMETER,
"Error parsing xml-rpc stream", "Method: "+sMethod);
throwError(derr);
return xmlrpcReturnFault(derr);
}
//Start own method handler
methodResult = methodHandlerOwn(sMethod, daArgs, user,cookie);
derr = xmlRpcGetErrorFromResult(methodResult); /* Get error from result if error occurred */
if (dynlen(derr) > 0) //Error occurred
{
throwError(derr);
// return fault
//Encode Error
return makeDynString(xmlrpcReturnFault(derr), "Content-Type: text/xml");
}
sRet = xmlrpcReturnSuccess(methodResult); //Encode result
//Compress the result if the other side allows it
if ( strlen(sRet) > 1024 && strpos(httpGetHeader(connIdx, "Accept-Encoding"),"gzip") >= 0)
{
//Return compressed content
blob b;
gzip(sRet, b);
xmlResult = makeDynMixed(b, "Content-Type: text/xml", "Content-Encoding: gzip");
}
else
{
//Return plain content
xmlResult = makeDynString(sRet, "Content-Type: text/xml");
}
return xmlResult;
}
mixed methodHandlerOwn(string sMethod, dyn_mixed &asValues, string user, string cookie)
{
switch (sMethod)
{
case "wccoa.own.testmethod" :
return xmlrpc_wccoa_own_testmethod(sMethod, asValues);
default :
return methodHandlerCommon(sMethod, asValues, user, cookie);
}
}
private mixed xmlrpc_wccoa_own_testmethod(string sMethod, dyn_mixed values)
{
mixed res;
string name;
//Check parameters
if (dynlen(values) >= 2)
return xmlRpcMakeError(PRIO_SEVERE, ERR_CONTROL, ERR_INVALID_ARGUMENT, sMethod, ""+values);
//Magic Code:
name = values[1];
res = "Hello World"+name;
return res;
}
Client
Connect to the server as follows, call the function on the server as well as close the connection to the server:
#uses "CtrlXmlRpc"
main()
{
string id = "servID";
string func = "wccoa.own.testmethod";
dyn_mixed args = makeDynString("World");;
mixed res;
string host = "localhost";
int port = "80";
bool secure = FALSE;
xmlrpcClient();
xmlrpcConnectToServer(id, host, port, secure);
xmlrpcCall(id, func, args, res);
DebugN("Result of XmlRpc call", res);
xmlrpcCloseServer(id);
}