Respect the no_proxy environment variable.
authorCory Benfield <lukasaoz@gmail.com>
Sun, 18 Nov 2012 12:06:33 +0000 (12:06 +0000)
committerCory Benfield <lukasaoz@gmail.com>
Sun, 18 Nov 2012 12:06:33 +0000 (12:06 +0000)
This change is in response to issue #879.

requests/models.py
requests/utils.py
tests/test_utils.py

index 58e7f9a774fa5429f0cd3a65057cc253e663b6b6..9c0666a6094e3c4f2d6b17d4fab75dd29c64b9ff 100644 (file)
@@ -119,7 +119,7 @@ class Request(object):
         # If no proxies are given, allow configuration by environment variables
         # HTTP_PROXY and HTTPS_PROXY.
         if not self.proxies and self.config.get('trust_env'):
-            self.proxies = get_environ_proxies()
+            self.proxies = get_environ_proxies(self.url)
 
         self.data = data
         self.params = params
index b3d33f4fbc2dbe9c7591db0fc8fd82a424fda57f..fef2d83f51561035d250d69a59b2471a0309efbf 100644 (file)
@@ -502,7 +502,7 @@ def requote_uri(uri):
     return quote(unquote_unreserved(uri), safe="!#$%&'()*+,/:;=?@[]~")
 
 
-def get_environ_proxies():
+def get_environ_proxies(url):
     """Return a dict of environment proxies."""
 
     proxy_keys = [
@@ -510,11 +510,29 @@ def get_environ_proxies():
         'http',
         'https',
         'ftp',
-        'socks',
-        'no'
+        'socks'
     ]
 
     get_proxy = lambda k: os.environ.get(k) or os.environ.get(k.upper())
+
+    # First check whether no_proxy is defined. If it is, check that the URL
+    # we're getting isn't in the no_proxy list.
+    no_proxy = get_proxy('no_proxy')
+
+    if no_proxy:
+        # We need to check whether we match here. We need to see if we match
+        # the end of the netloc, both with and without the port.
+        no_proxy = no_proxy.split(',')
+        netloc = urlparse(url).netloc
+
+        for host in no_proxy:
+            if netloc.endswith(host) or netloc.split(':')[0].endswith(host):
+                # The URL does match something in no_proxy, so we don't want
+                # to apply the proxies on this URL.
+                return {}
+
+    # If we get here, we either didn't have no_proxy set or we're not going
+    # anywhere that no_proxy applies to.
     proxies = [(key, get_proxy(key + '_proxy')) for key in proxy_keys]
     return dict([(key, val) for (key, val) in proxies if val])
 
index 5cd0684e85c77fafb6d70174ea97f139c09d43f0..7febc570677a2bed5456a41abb10eedbfcc9ac1a 100644 (file)
@@ -9,6 +9,7 @@ import random
 
 # Path hack.
 sys.path.insert(0, os.path.abspath('..'))
+from requests.utils import get_environ_proxies
 import requests.utils
 from requests.compat import is_py3, bytes
 
@@ -20,7 +21,7 @@ else:
     byteschr = chr
 
 
-class GuessJSONUTFTests(unittest.TestCase):
+class UtilityTests(unittest.TestCase):
     """Tests for the JSON UTF encoding guessing code."""
 
     codecs = (
@@ -73,5 +74,28 @@ class GuessJSONUTFTests(unittest.TestCase):
                         continue
                     raise
 
+    def test_get_environ_proxies_respects_no_proxy(self):
+        '''This test confirms that the no_proxy environment setting is
+        respected by get_environ_proxies().'''
+
+        # Set up some example environment settings.
+        os.environ['http_proxy'] = 'http://www.example.com/'
+        os.environ['no_proxy'] = r'localhost,.0.0.1:8080'
+
+        # Set up expected proxy return values.
+        proxy_yes = {'http': 'http://www.example.com/'}
+        proxy_no = {}
+
+        # Check that we get the right things back.
+        self.assertEqual(proxy_yes,
+                         get_environ_proxies('http://www.google.com/'))
+        self.assertEqual(proxy_no,
+                         get_environ_proxies('http://localhost/test'))
+        self.assertEqual(proxy_no,
+                         get_environ_proxies('http://127.0.0.1:8080/'))
+        self.assertEqual(proxy_yes,
+                         get_environ_proxies('http://127.0.0.1:8081/'))
+
+
 if __name__ == '__main__':
     unittest.main()