mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +00:00 
			
		
		
		
	Issue #26804: urllib.request will prefer lower_case proxy environment variables
over UPPER_CASE or Mixed_Case ones. Patch contributed by Hans-Peter Jansen. Reviewed by Martin Panter and Senthil Kumaran.
This commit is contained in:
		
							parent
							
								
									d3304e3e20
								
							
						
					
					
						commit
						a7c0ff2f0b
					
				
					 5 changed files with 80 additions and 11 deletions
				
			
		| 
						 | 
					@ -166,6 +166,8 @@ The :mod:`urllib.request` module defines the following functions:
 | 
				
			||||||
   in a case insensitive approach, for all operating systems first, and when it
 | 
					   in a case insensitive approach, for all operating systems first, and when it
 | 
				
			||||||
   cannot find it, looks for proxy information from Mac OSX System
 | 
					   cannot find it, looks for proxy information from Mac OSX System
 | 
				
			||||||
   Configuration for Mac OS X and Windows Systems Registry for Windows.
 | 
					   Configuration for Mac OS X and Windows Systems Registry for Windows.
 | 
				
			||||||
 | 
					   If both lowercase and uppercase environment variables exist (and disagree),
 | 
				
			||||||
 | 
					   lowercase is preferred.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The following classes are provided:
 | 
					The following classes are provided:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -226,8 +226,46 @@ def test_getproxies_environment_keep_no_proxies(self):
 | 
				
			||||||
        # getproxies_environment use lowered case truncated (no '_proxy') keys
 | 
					        # getproxies_environment use lowered case truncated (no '_proxy') keys
 | 
				
			||||||
        self.assertEqual('localhost', proxies['no'])
 | 
					        self.assertEqual('localhost', proxies['no'])
 | 
				
			||||||
        # List of no_proxies with space.
 | 
					        # List of no_proxies with space.
 | 
				
			||||||
        self.env.set('NO_PROXY', 'localhost, anotherdomain.com, newdomain.com')
 | 
					        self.env.set('NO_PROXY', 'localhost, anotherdomain.com, newdomain.com:1234')
 | 
				
			||||||
        self.assertTrue(urllib.request.proxy_bypass_environment('anotherdomain.com'))
 | 
					        self.assertTrue(urllib.request.proxy_bypass_environment('anotherdomain.com'))
 | 
				
			||||||
 | 
					        self.assertTrue(urllib.request.proxy_bypass_environment('anotherdomain.com:8888'))
 | 
				
			||||||
 | 
					        self.assertTrue(urllib.request.proxy_bypass_environment('newdomain.com:1234'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProxyTests_withOrderedEnv(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def setUp(self):
 | 
				
			||||||
 | 
					        # We need to test conditions, where variable order _is_ significant
 | 
				
			||||||
 | 
					        self._saved_env = os.environ
 | 
				
			||||||
 | 
					        # Monkey patch os.environ, start with empty fake environment
 | 
				
			||||||
 | 
					        os.environ = collections.OrderedDict()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def tearDown(self):
 | 
				
			||||||
 | 
					        os.environ = self._saved_env
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_getproxies_environment_prefer_lowercase(self):
 | 
				
			||||||
 | 
					        # Test lowercase preference with removal
 | 
				
			||||||
 | 
					        os.environ['no_proxy'] = ''
 | 
				
			||||||
 | 
					        os.environ['No_Proxy'] = 'localhost'
 | 
				
			||||||
 | 
					        self.assertFalse(urllib.request.proxy_bypass_environment('localhost'))
 | 
				
			||||||
 | 
					        self.assertFalse(urllib.request.proxy_bypass_environment('arbitrary'))
 | 
				
			||||||
 | 
					        os.environ['http_proxy'] = ''
 | 
				
			||||||
 | 
					        os.environ['HTTP_PROXY'] = 'http://somewhere:3128'
 | 
				
			||||||
 | 
					        proxies = urllib.request.getproxies_environment()
 | 
				
			||||||
 | 
					        self.assertEqual({}, proxies)
 | 
				
			||||||
 | 
					        # Test lowercase preference of proxy bypass and correct matching including ports
 | 
				
			||||||
 | 
					        os.environ['no_proxy'] = 'localhost, noproxy.com, my.proxy:1234'
 | 
				
			||||||
 | 
					        os.environ['No_Proxy'] = 'xyz.com'
 | 
				
			||||||
 | 
					        self.assertTrue(urllib.request.proxy_bypass_environment('localhost'))
 | 
				
			||||||
 | 
					        self.assertTrue(urllib.request.proxy_bypass_environment('noproxy.com:5678'))
 | 
				
			||||||
 | 
					        self.assertTrue(urllib.request.proxy_bypass_environment('my.proxy:1234'))
 | 
				
			||||||
 | 
					        self.assertFalse(urllib.request.proxy_bypass_environment('my.proxy'))
 | 
				
			||||||
 | 
					        self.assertFalse(urllib.request.proxy_bypass_environment('arbitrary'))
 | 
				
			||||||
 | 
					        # Test lowercase preference with replacement
 | 
				
			||||||
 | 
					        os.environ['http_proxy'] = 'http://somewhere:3128'
 | 
				
			||||||
 | 
					        os.environ['Http_Proxy'] = 'http://somewhereelse:3128'
 | 
				
			||||||
 | 
					        proxies = urllib.request.getproxies_environment()
 | 
				
			||||||
 | 
					        self.assertEqual('http://somewhere:3128', proxies['http'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class urlopen_HttpTests(unittest.TestCase, FakeHTTPMixin, FakeFTPMixin):
 | 
					class urlopen_HttpTests(unittest.TestCase, FakeHTTPMixin, FakeFTPMixin):
 | 
				
			||||||
    """Test urlopen() opening a fake http connection."""
 | 
					    """Test urlopen() opening a fake http connection."""
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2395,19 +2395,35 @@ def getproxies_environment():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    proxies = {}
 | 
					    proxies = {}
 | 
				
			||||||
 | 
					    # in order to prefer lowercase variables, process environment in
 | 
				
			||||||
 | 
					    # two passes: first matches any, second pass matches lowercase only
 | 
				
			||||||
    for name, value in os.environ.items():
 | 
					    for name, value in os.environ.items():
 | 
				
			||||||
        name = name.lower()
 | 
					        name = name.lower()
 | 
				
			||||||
        if value and name[-6:] == '_proxy':
 | 
					        if value and name[-6:] == '_proxy':
 | 
				
			||||||
            proxies[name[:-6]] = value
 | 
					            proxies[name[:-6]] = value
 | 
				
			||||||
 | 
					    for name, value in os.environ.items():
 | 
				
			||||||
 | 
					        if name[-6:] == '_proxy':
 | 
				
			||||||
 | 
					            name = name.lower()
 | 
				
			||||||
 | 
					            if value:
 | 
				
			||||||
 | 
					                proxies[name[:-6]] = value
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                proxies.pop(name[:-6], None)
 | 
				
			||||||
    return proxies
 | 
					    return proxies
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def proxy_bypass_environment(host):
 | 
					def proxy_bypass_environment(host, proxies=None):
 | 
				
			||||||
    """Test if proxies should not be used for a particular host.
 | 
					    """Test if proxies should not be used for a particular host.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Checks the environment for a variable named no_proxy, which should
 | 
					    Checks the proxy dict for the value of no_proxy, which should
 | 
				
			||||||
    be a list of DNS suffixes separated by commas, or '*' for all hosts.
 | 
					    be a list of comma separated DNS suffixes, or '*' for all hosts.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    no_proxy = os.environ.get('no_proxy', '') or os.environ.get('NO_PROXY', '')
 | 
					    if proxies is None:
 | 
				
			||||||
 | 
					        proxies = getproxies_environment()
 | 
				
			||||||
 | 
					    # don't bypass, if no_proxy isn't specified
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        no_proxy = proxies['no']
 | 
				
			||||||
 | 
					    except KeyError:
 | 
				
			||||||
 | 
					        return 0
 | 
				
			||||||
    # '*' is special case for always bypass
 | 
					    # '*' is special case for always bypass
 | 
				
			||||||
    if no_proxy == '*':
 | 
					    if no_proxy == '*':
 | 
				
			||||||
        return 1
 | 
					        return 1
 | 
				
			||||||
| 
						 | 
					@ -2502,8 +2518,15 @@ def getproxies_macosx_sysconf():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def proxy_bypass(host):
 | 
					    def proxy_bypass(host):
 | 
				
			||||||
        if getproxies_environment():
 | 
					        """Return True, if host should be bypassed.
 | 
				
			||||||
            return proxy_bypass_environment(host)
 | 
					
 | 
				
			||||||
 | 
					        Checks proxy settings gathered from the environment, if specified,
 | 
				
			||||||
 | 
					        or from the MacOSX framework SystemConfiguration.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        proxies = getproxies_environment()
 | 
				
			||||||
 | 
					        if proxies:
 | 
				
			||||||
 | 
					            return proxy_bypass_environment(host, proxies)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            return proxy_bypass_macosx_sysconf(host)
 | 
					            return proxy_bypass_macosx_sysconf(host)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2617,14 +2640,15 @@ def proxy_bypass_registry(host):
 | 
				
			||||||
        return 0
 | 
					        return 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def proxy_bypass(host):
 | 
					    def proxy_bypass(host):
 | 
				
			||||||
        """Return a dictionary of scheme -> proxy server URL mappings.
 | 
					        """Return True, if host should be bypassed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Returns settings gathered from the environment, if specified,
 | 
					        Checks proxy settings gathered from the environment, if specified,
 | 
				
			||||||
        or the registry.
 | 
					        or the registry.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if getproxies_environment():
 | 
					        proxies = getproxies_environment()
 | 
				
			||||||
            return proxy_bypass_environment(host)
 | 
					        if proxies:
 | 
				
			||||||
 | 
					            return proxy_bypass_environment(host, proxies)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            return proxy_bypass_registry(host)
 | 
					            return proxy_bypass_registry(host)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -670,6 +670,7 @@ Kjetil Jacobsen
 | 
				
			||||||
Bertrand Janin
 | 
					Bertrand Janin
 | 
				
			||||||
Geert Jansen
 | 
					Geert Jansen
 | 
				
			||||||
Jack Jansen
 | 
					Jack Jansen
 | 
				
			||||||
 | 
					Hans-Peter Jansen
 | 
				
			||||||
Bill Janssen
 | 
					Bill Janssen
 | 
				
			||||||
Thomas Jarosch
 | 
					Thomas Jarosch
 | 
				
			||||||
Juhana Jauhiainen
 | 
					Juhana Jauhiainen
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -107,6 +107,10 @@ Core and Builtins
 | 
				
			||||||
Library
 | 
					Library
 | 
				
			||||||
-------
 | 
					-------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Issue #26804: urllib.request will prefer lower_case proxy environment
 | 
				
			||||||
 | 
					  variables over UPPER_CASE or Mixed_Case ones. Patch contributed by Hans-Peter
 | 
				
			||||||
 | 
					  Jansen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Issue #26837: assertSequenceEqual() now correctly outputs non-stringified
 | 
					- Issue #26837: assertSequenceEqual() now correctly outputs non-stringified
 | 
				
			||||||
  differing items (like bytes in the -b mode).  This affects assertListEqual()
 | 
					  differing items (like bytes in the -b mode).  This affects assertListEqual()
 | 
				
			||||||
  and assertTupleEqual().
 | 
					  and assertTupleEqual().
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue