bugzilla: make XMLRPC interface support http and https access stable
authorJim Hague <jim.hague@acm.org>
Wed, 11 Jan 2012 16:54:29 +0000
branchstable
changeset 15870 f4c859293ed4
parent 15848 012b285cf643
child 15871 07893690c435
bugzilla: make XMLRPC interface support http and https access Inadvertently support is currently only for https. For some reason I thought xmlrpclib.SafeTransport did http and https, but it is https only. So create http and https XMLRPC transports that retain cookies. Decide which to use by inspecting the Bugzilla URL.
hgext/bugzilla.py
--- a/hgext/bugzilla.py	Thu Jan 12 00:49:45 2012 +0900
+++ b/hgext/bugzilla.py	Wed Jan 11 16:54:29 2012 +0000
@@ -255,7 +255,7 @@
 from mercurial.i18n import _
 from mercurial.node import short
 from mercurial import cmdutil, mail, templater, util
-import re, time, xmlrpclib
+import re, time, urlparse, xmlrpclib
 
 class bzaccess(object):
     '''Base class for access to Bugzilla.'''
@@ -473,17 +473,16 @@
 
 # Buzgilla via XMLRPC interface.
 
-class CookieSafeTransport(xmlrpclib.SafeTransport):
-    """A SafeTransport that retains cookies over its lifetime.
+class cookietransportrequest(object):
+    """A Transport request method that retains cookies over its lifetime.
 
     The regular xmlrpclib transports ignore cookies. Which causes
     a bit of a problem when you need a cookie-based login, as with
     the Bugzilla XMLRPC interface.
 
-    So this is a SafeTransport which looks for cookies being set
-    in responses and saves them to add to all future requests.
-    It appears a SafeTransport can do both HTTP and HTTPS sessions,
-    which saves us having to do a CookieTransport too.
+    So this is a helper for defining a Transport which looks for
+    cookies being set in responses and saves them to add to all future
+    requests.
     """
 
     # Inspiration drawn from
@@ -537,6 +536,18 @@
 
         return unmarshaller.close()
 
+# The explicit calls to the underlying xmlrpclib __init__() methods are
+# necessary. The xmlrpclib.Transport classes are old-style classes, and
+# it turns out their __init__() doesn't get called when doing multiple
+# inheritance with a new-style class.
+class cookietransport(cookietransportrequest, xmlrpclib.Transport):
+    def __init__(self, use_datetime=0):
+        xmlrpclib.Transport.__init__(self, use_datetime)
+
+class cookiesafetransport(cookietransportrequest, xmlrpclib.SafeTransport):
+    def __init__(self, use_datetime=0):
+        xmlrpclib.SafeTransport.__init__(self, use_datetime)
+
 class bzxmlrpc(bzaccess):
     """Support for access to Bugzilla via the Bugzilla XMLRPC API.
 
@@ -553,9 +564,15 @@
         user = self.ui.config('bugzilla', 'user', 'bugs')
         passwd = self.ui.config('bugzilla', 'password')
 
-        self.bzproxy = xmlrpclib.ServerProxy(bzweb, CookieSafeTransport())
+        self.bzproxy = xmlrpclib.ServerProxy(bzweb, self.transport(bzweb))
         self.bzproxy.User.login(dict(login=user, password=passwd))
 
+    def transport(self, uri):
+        if urlparse.urlparse(uri, "http")[0] == "https":
+            return cookiesafetransport()
+        else:
+            return cookietransport()
+
     def get_bug_comments(self, id):
         """Return a string with all comment text for a bug."""
         c = self.bzproxy.Bug.comments(dict(ids=[id]))