See introduction to XMLAPI for details on Authentication:
https://support.sippysoft.com/a/solutions/articles/106909
Starting from Sippy 4.4 it's possible to use MULTICALL in XMLAPI.
This feature allows to "pack" N XMLAPI call into a single request to send to Server, instead of sending them one by one.
Measured benchmark for the addDID() xmlapi call showed 3 times faster execution in multicall compared with regular one-by-one addition of 1000 DIDs:
- 5m 20s in regular mode
- 1m 39s in multicall.
PYTHON example (updated):
Note: This updated Python example replaces httplib2 with the requests library to handle HTTP requests. By using requests.post() along with the appropriate URL, request body, and headers, the process is simplified, ensuring compatibility with newer Python versions (e.g., 3.11). Also requests by default writes more information about its internal work for example, errors or warnings about SSL settings.
#!/usr/bin/env python
import requests
from requests.auth import HTTPDigestAuth
try:
from urllib.parse import urlparse
from xmlrpc.client import ServerProxy, getparser, ProtocolError, MultiCall
except ImportError:
from urlparse import urlparse
from xmlrpclib import ServerProxy, getparser, ProtocolError, MultiCall
class HTTPSDigestAuthTransport:
def request(self, host, handler, request_body, verbose=0):
parsed = urlparse("https://" + host)
username = parsed.username
password = parsed.password
hostname = parsed.hostname
port = parsed.port or 443
url = f"https://{hostname}:{port}{handler}"
if verbose:
print(f"Making request to: {url}")
response = requests.post(url, data=request_body, headers={'content-type': 'text/xml'}, auth=HTTPDigestAuth(username, password), verify=True)
if response.status_code != 200:
raise ProtocolError(url, response.status_code, response.reason, None)
p, u = getparser(0)
p.feed(response.content)
return u.close()
if __name__ == "__main__":
transport = HTTPSDigestAuthTransport()
client = ServerProxy("https://username:password@1.2.3.4/xmlapi/xmlapi", transport)
multicall = MultiCall(client)
multicall.getAccountCallStats({"i_account": 1})
multicall.getAccountCallStats({"i_account": 1})
multicall.getAccountInfo({"i_account": -1}) # expect error here
multicall.getAccountCallStats({"i_account": 1})
for res in multicall().results:
if isinstance(res, dict):
print("Fault", res)
else:
print(res[0])PYTHON example (using httplib2):
Below is an example using httplib2. Although the scripts above are now based on requests, this code is still functional in Python 3 and might be useful for backward compatibility or for users who prefer httplib2.
#!/usr/bin/env python
import warnings
warnings.simplefilter("ignore", DeprecationWarning)
import httplib2
try:
from urllib.parse import splituser, splitpasswd
from xmlrpc.client import ServerProxy, getparser, ProtocolError, MultiCall
except ImportError:
from urllib import splituser, splitpasswd
from xmlrpclib import ServerProxy, getparser, ProtocolError, MultiCall
class HTTPSDigestAuthTransport:
def request(self, host, handler, request_body, verbose=0):
auth, host = splituser(host)
username, password = splitpasswd(auth)
h = httplib2.Http(disable_ssl_certificate_validation=True)
if verbose:
h.debuglevel = 1
h.add_credentials(username, password)
resp, content = h.request("https://" + host + handler, "POST", body=request_body,
headers={'content-type':'text/xml'})
if resp.status != 200:
raise ProtocolError("https://" + host + handler, resp.status, resp.reason, None)
p, u = getparser(0)
p.feed(content)
return u.close()
transport = HTTPSDigestAuthTransport()
client = ServerProxy("https://username:password@1.2.3.4/xmlapi/xmlapi", transport)
multicall = MultiCall(client)
multicall.getAccountCallStats({ "i_account" : 1})
multicall.getAccountCallStats({ "i_account" : 1})
multicall.getAccountInfo({ "i_account" : -1}) # expect error here
multicall.getAccountCallStats({ "i_account" : 1})
for res in multicall().results:
if isinstance(res, dict):
print ("Fault", res)
else:
print (res[0])More python examples:
https://support.sippysoft.com/a/solutions/articles/107511
PHP example:
<?
set_include_path(get_include_path() . PATH_SEPARATOR . '/home/ssp/sippy_web/lib');
include 'xmlrpc/xmlrpc.inc';
$customer_web_login = "username";
$customer_api_password = "password";
$params = array(new xmlrpcval(array(
"i_environment" => new xmlrpcval('1', "int"),
), 'struct'));
$msg = new xmlrpcmsg('getAccountCallStats', $params);
$params2 = array(new xmlrpcval(array(
"i_account" => new xmlrpcval('-1', "int"), // expect error
), 'struct'));
$msg2 = new xmlrpcmsg('getAccountInfo', $params2);
$cli = new xmlrpc_client('https://1.2.3.4/xmlapi/xmlapi');
$cli->request_charset_encoding = 'UTF-8';
$cli->setSSLVerifyPeer(false);
$cli->return_type = 'phpvals';
$cli->setDebug(2);
//$cli->setCredentials($customer_web_login, $customer_api_password, CURLAUTH_DIGEST);
$r = $cli->multicall(Array($msg, $msg, $msg2, $msg), 10, '', FALSE);
print_r($r);
?>