Skip to content

Commit 6a265f0

Browse files
bpo-39057: Fix urllib.request.proxy_bypass_environment(). (GH-17619)
Ignore leading dots and no longer ignore a trailing newline.
1 parent ec007cb commit 6a265f0

File tree

4 files changed

+39
-13
lines changed

4 files changed

+39
-13
lines changed

Lib/test/test_urllib.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,14 +270,36 @@ def test_proxy_bypass_environment_host_match(self):
270270
self.assertTrue(bypass('localhost'))
271271
self.assertTrue(bypass('LocalHost')) # MixedCase
272272
self.assertTrue(bypass('LOCALHOST')) # UPPERCASE
273+
self.assertTrue(bypass('.localhost'))
273274
self.assertTrue(bypass('newdomain.com:1234'))
275+
self.assertTrue(bypass('.newdomain.com:1234'))
274276
self.assertTrue(bypass('foo.d.o.t')) # issue 29142
277+
self.assertTrue(bypass('d.o.t'))
275278
self.assertTrue(bypass('anotherdomain.com:8888'))
279+
self.assertTrue(bypass('.anotherdomain.com:8888'))
276280
self.assertTrue(bypass('www.newdomain.com:1234'))
277281
self.assertFalse(bypass('prelocalhost'))
278282
self.assertFalse(bypass('newdomain.com')) # no port
279283
self.assertFalse(bypass('newdomain.com:1235')) # wrong port
280284

285+
def test_proxy_bypass_environment_always_match(self):
286+
bypass = urllib.request.proxy_bypass_environment
287+
self.env.set('NO_PROXY', '*')
288+
self.assertTrue(bypass('newdomain.com'))
289+
self.assertTrue(bypass('newdomain.com:1234'))
290+
self.env.set('NO_PROXY', '*, anotherdomain.com')
291+
self.assertTrue(bypass('anotherdomain.com'))
292+
self.assertFalse(bypass('newdomain.com'))
293+
self.assertFalse(bypass('newdomain.com:1234'))
294+
295+
def test_proxy_bypass_environment_newline(self):
296+
bypass = urllib.request.proxy_bypass_environment
297+
self.env.set('NO_PROXY',
298+
'localhost, anotherdomain.com, newdomain.com:1234')
299+
self.assertFalse(bypass('localhost\n'))
300+
self.assertFalse(bypass('anotherdomain.com:8888\n'))
301+
self.assertFalse(bypass('newdomain.com:1234\n'))
302+
281303

282304
class ProxyTests_withOrderedEnv(unittest.TestCase):
283305

Lib/urllib/parse.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,9 +1056,9 @@ def _splitport(host):
10561056
"""splitport('host:port') --> 'host', 'port'."""
10571057
global _portprog
10581058
if _portprog is None:
1059-
_portprog = re.compile('(.*):([0-9]*)$', re.DOTALL)
1059+
_portprog = re.compile('(.*):([0-9]*)', re.DOTALL)
10601060

1061-
match = _portprog.match(host)
1061+
match = _portprog.fullmatch(host)
10621062
if match:
10631063
host, port = match.groups()
10641064
if port:

Lib/urllib/request.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2492,24 +2492,26 @@ def proxy_bypass_environment(host, proxies=None):
24922492
try:
24932493
no_proxy = proxies['no']
24942494
except KeyError:
2495-
return 0
2495+
return False
24962496
# '*' is special case for always bypass
24972497
if no_proxy == '*':
2498-
return 1
2498+
return True
2499+
host = host.lower()
24992500
# strip port off host
25002501
hostonly, port = _splitport(host)
25012502
# check if the host ends with any of the DNS suffixes
2502-
no_proxy_list = [proxy.strip() for proxy in no_proxy.split(',')]
2503-
for name in no_proxy_list:
2503+
for name in no_proxy.split(','):
2504+
name = name.strip()
25042505
if name:
25052506
name = name.lstrip('.') # ignore leading dots
2506-
name = re.escape(name)
2507-
pattern = r'(.+\.)?%s$' % name
2508-
if (re.match(pattern, hostonly, re.I)
2509-
or re.match(pattern, host, re.I)):
2510-
return 1
2507+
name = name.lower()
2508+
if hostonly == name or host == name:
2509+
return True
2510+
name = '.' + name
2511+
if hostonly.endswith(name) or host.endswith(name):
2512+
return True
25112513
# otherwise, don't bypass
2512-
return 0
2514+
return False
25132515

25142516

25152517
# This code tests an OSX specific data structure but is testable on all
@@ -2635,7 +2637,7 @@ def getproxies_registry():
26352637
for p in proxyServer.split(';'):
26362638
protocol, address = p.split('=', 1)
26372639
# See if address has a type:// prefix
2638-
if not re.match('^([^/:]+)://', address):
2640+
if not re.match('(?:[^/:]+)://', address):
26392641
address = '%s://%s' % (protocol, address)
26402642
proxies[protocol] = address
26412643
else:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:func:`urllib.request.proxy_bypass_environment` now ignores leading dots and
2+
no longer ignores a trailing newline.

0 commit comments

Comments
 (0)