[Python-checkins] r74204 - in python/branches/release31-maint: Lib/http/client.py Lib/test/test_urllib2.py Lib/urllib/request.py Misc/NEWS

senthil.kumaran python-checkins at python.org
Sun Jul 26 14:39:48 CEST 2009


Author: senthil.kumaran
Date: Sun Jul 26 14:39:47 2009
New Revision: 74204

Log:
Backport the changes made in revision 74198, fixing the issue 1424152



Modified:
   python/branches/release31-maint/Lib/http/client.py
   python/branches/release31-maint/Lib/test/test_urllib2.py
   python/branches/release31-maint/Lib/urllib/request.py
   python/branches/release31-maint/Misc/NEWS

Modified: python/branches/release31-maint/Lib/http/client.py
==============================================================================
--- python/branches/release31-maint/Lib/http/client.py	(original)
+++ python/branches/release31-maint/Lib/http/client.py	Sun Jul 26 14:39:47 2009
@@ -644,11 +644,17 @@
         self.__response = None
         self.__state = _CS_IDLE
         self._method = None
+        self._tunnel_host = None
+        self._tunnel_port = None
 
         self._set_hostport(host, port)
         if strict is not None:
             self.strict = strict
 
+    def _set_tunnel(self, host, port=None):
+        self._tunnel_host = host
+        self._tunnel_port = port
+
     def _set_hostport(self, host, port):
         if port is None:
             i = host.rfind(':')
@@ -669,10 +675,29 @@
     def set_debuglevel(self, level):
         self.debuglevel = level
 
+    def _tunnel(self):
+        self._set_hostport(self._tunnel_host, self._tunnel_port)
+        connect_str = "CONNECT %s:%d HTTP/1.0\r\n\r\n" %(self.host, self.port)
+        connect_bytes = connect_str.encode("ascii")
+        self.send(connect_bytes)
+        response = self.response_class(self.sock, strict = self.strict,
+                                       method= self._method)
+        (version, code, message) = response._read_status()
+        if code != 200:
+            self.close()
+            raise socket.error("Tunnel connection failed: %d %s" % (code,
+                                                                    message.strip()))
+        while True:
+            line = response.fp.readline()
+            if line == b'\r\n':
+                break
+
     def connect(self):
         """Connect to the host and port specified in __init__."""
         self.sock = socket.create_connection((self.host,self.port),
                                              self.timeout)
+        if self._tunnel_host:
+            self._tunnel()
 
     def close(self):
         """Close the connection to the HTTP server."""
@@ -1008,6 +1033,11 @@
 
             sock = socket.create_connection((self.host, self.port),
                                             self.timeout)
+
+            if self._tunnel_host:
+                self.sock = sock
+                self._tunnel()
+
             self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)
 
 

Modified: python/branches/release31-maint/Lib/test/test_urllib2.py
==============================================================================
--- python/branches/release31-maint/Lib/test/test_urllib2.py	(original)
+++ python/branches/release31-maint/Lib/test/test_urllib2.py	Sun Jul 26 14:39:47 2009
@@ -947,6 +947,23 @@
         self.assertEqual([(handlers[0], "http_open")],
                          [tup[0:2] for tup in o.calls])
 
+    def test_proxy_https(self):
+        o = OpenerDirector()
+        ph = urllib.request.ProxyHandler(dict(https="proxy.example.com:3128"))
+        o.add_handler(ph)
+        meth_spec = [
+            [("https_open", "return response")]
+        ]
+        handlers = add_ordered_mock_handlers(o, meth_spec)
+
+        req = Request("https://www.example.com/")
+        self.assertEqual(req.get_host(), "www.example.com")
+        r = o.open(req)
+        self.assertEqual(req.get_host(), "proxy.example.com:3128")
+        self.assertEqual([(handlers[0], "https_open")],
+                         [tup[0:2] for tup in o.calls])
+
+
     def test_basic_auth(self, quote_char='"'):
         opener = OpenerDirector()
         password_manager = MockPasswordManager()

Modified: python/branches/release31-maint/Lib/urllib/request.py
==============================================================================
--- python/branches/release31-maint/Lib/urllib/request.py	(original)
+++ python/branches/release31-maint/Lib/urllib/request.py	Sun Jul 26 14:39:47 2009
@@ -163,6 +163,7 @@
         self.full_url = unwrap(url)
         self.data = data
         self.headers = {}
+        self._tunnel_host = None
         for key, value in headers.items():
             self.add_header(key, value)
         self.unredirected_hdrs = {}
@@ -218,8 +219,12 @@
     # End deprecated methods
 
     def set_proxy(self, host, type):
-        self.host, self.type = host, type
-        self.selector = self.full_url
+        if self.type == 'https' and not self._tunnel_host:
+            self._tunnel_host = self.host
+        else:
+            self.type= type
+            self.selector = self.full_url
+        self.host = host
 
     def has_proxy(self):
         return self.selector == self.full_url
@@ -659,7 +664,7 @@
             req.add_header('Proxy-authorization', 'Basic ' + creds)
         hostport = unquote(hostport)
         req.set_proxy(hostport, proxy_type)
-        if orig_type == proxy_type:
+        if orig_type == proxy_type or orig_type == 'https':
             # let other handlers take care of it
             return None
         else:
@@ -1041,6 +1046,10 @@
         # request.
         headers["Connection"] = "close"
         headers = dict((name.title(), val) for name, val in headers.items())
+
+        if req._tunnel_host:
+            h._set_tunnel(req._tunnel_host)
+
         try:
             h.request(req.get_method(), req.selector, req.data, headers)
             r = h.getresponse()  # an HTTPResponse instance

Modified: python/branches/release31-maint/Misc/NEWS
==============================================================================
--- python/branches/release31-maint/Misc/NEWS	(original)
+++ python/branches/release31-maint/Misc/NEWS	Sun Jul 26 14:39:47 2009
@@ -39,6 +39,10 @@
 Library
 -------
 
+- Issue #1424152: Fix for http.client, urllib.request to support SSL while
+  working through proxy. Original patch by Christopher Li, changes made by
+  Senthil Kumaran
+
 - importlib.abc.PyLoader did not inherit from importlib.abc.ResourceLoader like
   the documentation said it did even though the code in PyLoader relied on the
   abstract method required by ResourceLoader.


More information about the Python-checkins mailing list