[Python-checkins] cpython: Issue #17107: Test client-side SNI support in urllib.request thanks to the new

antoine.pitrou python-checkins at python.org
Tue Feb 5 21:24:58 CET 2013


http://hg.python.org/cpython/rev/f74a12e23aaa
changeset:   82026:f74a12e23aaa
user:        Antoine Pitrou <solipsis at pitrou.net>
date:        Tue Feb 05 21:20:51 2013 +0100
summary:
  Issue #17107: Test client-side SNI support in urllib.request thanks to the new server-side SNI support in the ssl module.
Initial patch by Daniel Black.

files:
  Lib/test/ssl_servers.py           |   8 +++--
  Lib/test/test_httplib.py          |   2 +-
  Lib/test/test_ssl.py              |   2 +-
  Lib/test/test_urllib2_localnet.py |  28 ++++++++++++++++--
  Lib/test/test_urllib2net.py       |  22 --------------
  Misc/NEWS                         |   4 ++
  6 files changed, 36 insertions(+), 30 deletions(-)


diff --git a/Lib/test/ssl_servers.py b/Lib/test/ssl_servers.py
--- a/Lib/test/ssl_servers.py
+++ b/Lib/test/ssl_servers.py
@@ -147,9 +147,11 @@
         self.server.shutdown()
 
 
-def make_https_server(case, certfile=CERTFILE, host=HOST, handler_class=None):
-    # we assume the certfile contains both private key and certificate
-    context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
+def make_https_server(case, *, context=None, certfile=CERTFILE,
+                      host=HOST, handler_class=None):
+    if context is None:
+        context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
+    # We assume the certfile contains both private key and certificate
     context.load_cert_chain(certfile)
     server = HTTPSServerThread(context, host, handler_class)
     flag = threading.Event()
diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py
--- a/Lib/test/test_httplib.py
+++ b/Lib/test/test_httplib.py
@@ -703,7 +703,7 @@
 
     def make_server(self, certfile):
         from test.ssl_servers import make_https_server
-        return make_https_server(self, certfile)
+        return make_https_server(self, certfile=certfile)
 
     def test_attributes(self):
         # simple test to check it's storing the timeout
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -1637,7 +1637,7 @@
 
         def test_socketserver(self):
             """Using a SocketServer to create and manage SSL connections."""
-            server = make_https_server(self, CERTFILE)
+            server = make_https_server(self, certfile=CERTFILE)
             # try to connect
             if support.verbose:
                 sys.stdout.write('\n')
diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py
--- a/Lib/test/test_urllib2_localnet.py
+++ b/Lib/test/test_urllib2_localnet.py
@@ -9,7 +9,10 @@
 import hashlib
 from test import support
 threading = support.import_module('threading')
-
+try:
+    import ssl
+except ImportError:
+    ssl = None
 
 here = os.path.dirname(__file__)
 # Self-signed cert file for 'localhost'
@@ -17,6 +20,7 @@
 # Self-signed cert file for 'fakehostname'
 CERT_fakehostname = os.path.join(here, 'keycert2.pem')
 
+
 # Loopback http server infrastructure
 
 class LoopbackHttpServer(http.server.HTTPServer):
@@ -353,12 +357,15 @@
     def setUp(self):
         super(TestUrlopen, self).setUp()
         # Ignore proxies for localhost tests.
+        self.old_environ = os.environ.copy()
         os.environ['NO_PROXY'] = '*'
         self.server = None
 
     def tearDown(self):
         if self.server is not None:
             self.server.stop()
+        os.environ.clear()
+        os.environ.update(self.old_environ)
         super(TestUrlopen, self).tearDown()
 
     def urlopen(self, url, data=None, **kwargs):
@@ -386,14 +393,14 @@
         handler.port = port
         return handler
 
-    def start_https_server(self, responses=None, certfile=CERT_localhost):
+    def start_https_server(self, responses=None, **kwargs):
         if not hasattr(urllib.request, 'HTTPSHandler'):
             self.skipTest('ssl support required')
         from test.ssl_servers import make_https_server
         if responses is None:
             responses = [(200, [], b"we care a bit")]
         handler = GetRequestHandler(responses)
-        server = make_https_server(self, certfile=certfile, handler_class=handler)
+        server = make_https_server(self, handler_class=handler, **kwargs)
         handler.port = server.port
         return handler
 
@@ -483,6 +490,21 @@
             self.urlopen("https://localhost:%s/bizarre" % handler.port,
                          cadefault=True)
 
+    def test_https_sni(self):
+        if ssl is None:
+            self.skipTest("ssl module required")
+        if not ssl.HAS_SNI:
+            self.skipTest("SNI support required in OpenSSL")
+        sni_name = None
+        def cb_sni(ssl_sock, server_name, initial_context):
+            nonlocal sni_name
+            sni_name = server_name
+        context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
+        context.set_servername_callback(cb_sni)
+        handler = self.start_https_server(context=context, certfile=CERT_localhost)
+        self.urlopen("https://localhost:%s" % handler.port)
+        self.assertEqual(sni_name, "localhost")
+
     def test_sending_headers(self):
         handler = self.start_server()
         req = urllib.request.Request("http://localhost:%s/" % handler.port,
diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py
--- a/Lib/test/test_urllib2net.py
+++ b/Lib/test/test_urllib2net.py
@@ -330,31 +330,9 @@
             self.assertEqual(u.fp.fp.raw._sock.gettimeout(), 60)
 
 
- at unittest.skipUnless(ssl, "requires SSL support")
-class HTTPSTests(unittest.TestCase):
-
-    def test_sni(self):
-        self.skipTest("test disabled - test server needed")
-        # Checks that Server Name Indication works, if supported by the
-        # OpenSSL linked to.
-        # The ssl module itself doesn't have server-side support for SNI,
-        # so we rely on a third-party test site.
-        expect_sni = ssl.HAS_SNI
-        with support.transient_internet("XXX"):
-            u = urllib.request.urlopen("XXX")
-            contents = u.readall()
-            if expect_sni:
-                self.assertIn(b"Great", contents)
-                self.assertNotIn(b"Unfortunately", contents)
-            else:
-                self.assertNotIn(b"Great", contents)
-                self.assertIn(b"Unfortunately", contents)
-
-
 def test_main():
     support.requires("network")
     support.run_unittest(AuthTests,
-                         HTTPSTests,
                          OtherNetworkTests,
                          CloseSocketTest,
                          TimeoutTest,
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -754,6 +754,10 @@
 Tests
 -----
 
+- Issue #17107: Test client-side SNI support in urllib.request thanks to
+  the new server-side SNI support in the ssl module.  Initial patch by
+  Daniel Black.
+
 - Issue #17041: Fix testing when Python is configured with the
   --without-doc-strings.
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list