Changes from Version 1 of PyCURLTransport

Show
Ignore:
Author:
kad (IP: 91.154.113.243)
Timestamp:
03/21/08 01:44:50 (9 years ago)
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • PyCURLTransport

    v0 v1  
     1{{{ 
     2#!python 
     3#!/usr/bin/python -tt 
     4# vim: sw=4 ts=4 expandtab ai 
     5# 
     6# PyCURL based transports for xmlrpclib 
     7# 
     8# Copyright (C) 2008 Alexandr D. Kanevskiy <kad () bifh.org> 
     9# 
     10# Based on pycurl's example by Kjetil Jacobsen <kjetilja at gmail.com> 
     11# 
     12# This program is free software; you can redistribute it and/or 
     13# modify it under the terms of the GNU General Public License as 
     14# published by the Free Software Foundation; either version 2 of the 
     15# License. 
     16# 
     17# This program is distributed in the hope that it will be useful, but 
     18# WITHOUT ANY WARRANTY; without even the implied warranty of 
     19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     20# General Public License for more details. 
     21# 
     22# You should have received a copy of the GNU General Public License 
     23# along with this program; if not, write to the Free Software 
     24# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 
     25# 02110-1301 USA 
     26# 
     27# $Id$ 
     28 
     29try: 
     30    from cStringIO import StringIO 
     31except ImportError: 
     32    from StringIO import StringIO 
     33import xmlrpclib, pycurl, os 
     34 
     35 
     36class PyCURLTransport(xmlrpclib.Transport): 
     37    """Handles a cURL HTTP transaction to an XML-RPC server.""" 
     38 
     39    def __init__(self, username = None, password = None, timeout = 300): 
     40        xmlrpclib.Transport.__init__(self) 
     41 
     42        self.verbose = 0 
     43        self._proto = "http" 
     44 
     45        self._curl = pycurl.Curl() 
     46 
     47        # Suppress signals 
     48        self._curl.setopt(pycurl.NOSIGNAL, 1) 
     49 
     50        # Follow redirects 
     51        self._curl.setopt(pycurl.FOLLOWLOCATION, 1) 
     52 
     53        # Set timeouts 
     54        if timeout: 
     55            self._curl.setopt(pycurl.CONNECTTIMEOUT, timeout) 
     56            self._curl.setopt(pycurl.TIMEOUT, timeout) 
     57 
     58        # XML-RPC calls are POST (text/xml) 
     59        self._curl.setopt(pycurl.POST, 1) 
     60        self._curl.setopt(pycurl.HTTPHEADER, [ "Content-Type: text/xml" ]) 
     61 
     62        # Set auth info if defined 
     63        if username != None and password != None: 
     64            self._curl.setopt(pycurl.USERPWD, "%s:%s" % (username, password)) 
     65 
     66    def _check_return(self, host, handler, httpcode, buf): 
     67        """Checks return code for various errors""" 
     68        pass 
     69 
     70    def request(self, host, handler, request_body, verbose = 0): 
     71        """Performs actual request""" 
     72        buf = StringIO() 
     73        self._curl.setopt(pycurl.URL,  
     74                "%s://%s%s" % (self._proto, host, handler)) 
     75        self._curl.setopt(pycurl.POSTFIELDS, request_body) 
     76        self._curl.setopt(pycurl.WRITEFUNCTION, buf.write) 
     77        self._curl.setopt(pycurl.VERBOSE, verbose) 
     78        self.verbose = verbose 
     79        try: 
     80            self._curl.perform() 
     81            httpcode = self._curl.getinfo(pycurl.HTTP_CODE) 
     82        except pycurl.error, err: 
     83            raise xmlrpclib.ProtocolError(  
     84                    host + handler,  
     85                    err[0],  
     86                    err[1],  
     87                    None) 
     88 
     89        self._check_return(host, handler, httpcode, buf) 
     90 
     91        if httpcode != 200: 
     92            raise xmlrpclib.ProtocolError(  
     93                    host + handler,  
     94                    httpcode,  
     95                    buf.getvalue(),  
     96                    None) 
     97 
     98        buf.seek(0) 
     99        return self.parse_response(buf) 
     100 
     101 
     102class PyCURLSafeTransport(PyCURLTransport): 
     103    """Handles a cURL HTTP transaction to an XML-RPC server and also can validate certs.""" 
     104    def __init__(self, username = None, password = None, timeout = 300, cert = None): 
     105        PyCURLTransport.__init__(self, username, password, timeout) 
     106 
     107        self._proto = "https" 
     108 
     109        # Setup certificates 
     110        if cert is not None: 
     111            if os.path.exists(cert): 
     112                cert_path = cert 
     113            else: 
     114                from tempfile import NamedTemporaryFile 
     115                self.cert = NamedTemporaryFile(prefix = "cert") 
     116                self.cert.write(cert) 
     117                self.cert.flush() 
     118                cert_path = self.cert.name 
     119            self._curl.setopt(pycurl.CAINFO, cert_path) 
     120            self._curl.setopt(pycurl.SSL_VERIFYPEER, 2) 
     121            self._curl.setopt(pycurl.SSL_VERIFYHOST, 2) 
     122 
     123    def _check_return(self, host, handler, httpcode, buf): 
     124        """Check for SSL certs validity""" 
     125        if httpcode == 60: 
     126            raise xmlrpclib.ProtocolError(  
     127                    host + handler,  
     128                    httpcode,  
     129                    "SSL certificate validation failed",  
     130                    None) 
     131}}}