try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
import xmlrpclib, pycurl, os
class PyCURLTransport(xmlrpclib.Transport):
"""Handles a cURL HTTP transaction to an XML-RPC server."""
def __init__(self, username = None, password = None, timeout = 300):
xmlrpclib.Transport.__init__(self)
self.verbose = 0
self._proto = "http"
self._curl = pycurl.Curl()
self._curl.setopt(pycurl.NOSIGNAL, 1)
self._curl.setopt(pycurl.FOLLOWLOCATION, 1)
if timeout:
self._curl.setopt(pycurl.CONNECTTIMEOUT, timeout)
self._curl.setopt(pycurl.TIMEOUT, timeout)
self._curl.setopt(pycurl.POST, 1)
self._curl.setopt(pycurl.HTTPHEADER, [ "Content-Type: text/xml" ])
if username != None and password != None:
self._curl.setopt(pycurl.USERPWD, "%s:%s" % (username, password))
def _check_return(self, host, handler, httpcode, buf):
"""Checks return code for various errors"""
pass
def request(self, host, handler, request_body, verbose = 0):
"""Performs actual request"""
buf = StringIO()
self._curl.setopt(pycurl.URL,
"%s://%s%s" % (self._proto, host, handler))
self._curl.setopt(pycurl.POSTFIELDS, request_body)
self._curl.setopt(pycurl.WRITEFUNCTION, buf.write)
self._curl.setopt(pycurl.VERBOSE, verbose)
self.verbose = verbose
try:
self._curl.perform()
httpcode = self._curl.getinfo(pycurl.HTTP_CODE)
except pycurl.error, err:
raise xmlrpclib.ProtocolError(
host + handler,
err[0],
err[1],
None)
self._check_return(host, handler, httpcode, buf)
if httpcode != 200:
raise xmlrpclib.ProtocolError(
host + handler,
httpcode,
buf.getvalue(),
None)
buf.seek(0)
return self.parse_response(buf)
class PyCURLSafeTransport(PyCURLTransport):
"""Handles a cURL HTTP transaction to an XML-RPC server and also can validate certs."""
def __init__(self, username = None, password = None, timeout = 300, cert = None):
PyCURLTransport.__init__(self, username, password, timeout)
self._proto = "https"
if cert is not None:
if os.path.exists(cert):
cert_path = cert
else:
from tempfile import NamedTemporaryFile
self.cert = NamedTemporaryFile(prefix = "cert")
self.cert.write(cert)
self.cert.flush()
cert_path = self.cert.name
self._curl.setopt(pycurl.CAINFO, cert_path)
self._curl.setopt(pycurl.SSL_VERIFYPEER, 2)
self._curl.setopt(pycurl.SSL_VERIFYHOST, 2)
def _check_return(self, host, handler, httpcode, buf):
"""Check for SSL certs validity"""
if httpcode == 60:
raise xmlrpclib.ProtocolError(
host + handler,
httpcode,
"SSL certificate validation failed",
None)