Run xmlrpclib.Transport's __init__ too (required on F7).
[plcapi.git] / PLC / PyCurl.py
1 #
2 # Replacement for xmlrpclib.SafeTransport, which does not validate
3 # SSL certificates. Requires PyCurl.
4 #
5 # Mark Huang <mlhuang@cs.princeton.edu>
6 # Copyright (C) 2006 The Trustees of Princeton University
7 #
8 # $Id$
9 #
10
11 import os
12 import xmlrpclib
13 import pycurl
14 from tempfile import NamedTemporaryFile
15
16 class PyCurlTransport(xmlrpclib.Transport):
17     def __init__(self, uri, cert = None, timeout = 300):
18         xmlrpclib.Transport.__init__(self)
19         self.curl = pycurl.Curl()
20
21         # Suppress signals
22         self.curl.setopt(pycurl.NOSIGNAL, 1)
23
24         # Follow redirections
25         self.curl.setopt(pycurl.FOLLOWLOCATION, 1)
26
27         # Set URL
28         self.url = uri
29         self.curl.setopt(pycurl.URL, str(uri))
30
31         # Set certificate path
32         if cert is not None:
33             if os.path.exists(cert):
34                 cert_path = str(cert)
35             else:
36                 # Keep a reference so that it does not get deleted
37                 self.cert = NamedTemporaryFile(prefix = "cert")
38                 self.cert.write(cert)
39                 self.cert.flush()
40                 cert_path = self.cert.name
41             self.curl.setopt(pycurl.CAINFO, cert_path)
42             self.curl.setopt(pycurl.SSL_VERIFYPEER, 2)
43
44         # Set connection timeout
45         if timeout:
46             self.curl.setopt(pycurl.CONNECTTIMEOUT, timeout)
47             self.curl.setopt(pycurl.TIMEOUT, timeout)
48
49         # Set request callback
50         self.body = ""
51         def body(buf):
52             self.body += buf
53         self.curl.setopt(pycurl.WRITEFUNCTION, body)        
54
55     def request(self, host, handler, request_body, verbose = 1):
56         # Set verbosity
57         self.curl.setopt(pycurl.VERBOSE, verbose)
58
59         # Post request
60         self.curl.setopt(pycurl.POST, 1)
61         self.curl.setopt(pycurl.POSTFIELDS, request_body)
62
63         try:
64             self.curl.perform()
65             errcode = self.curl.getinfo(pycurl.HTTP_CODE)
66             response = self.body
67             self.body = ""
68         except pycurl.error, err:
69             (errcode, errmsg) = err
70
71         if errcode == 60:
72             raise Exception, "PyCurl: SSL certificate validation failed"
73         elif errcode != 200:
74             raise Exception, "PyCurl: HTTP error %d -- %r" % (errcode,errmsg)
75
76         # Parse response
77         p, u = self.getparser()
78         p.feed(response)
79         p.close()
80
81         return u.close()