From 8aff6f5ed0aca2dbe5b2eba242f0e3b96285c700 Mon Sep 17 00:00:00 2001 From: Kamil Madac Date: Tue, 3 Dec 2013 16:23:08 +0100 Subject: [PATCH] Redesigned no_proxy ip range imlementation to use only stdlib functions --- AUTHORS.rst | 1 + requests/utils.py | 55 ++++++++++++++++++++++++++++++++++------------- test_requests.py | 13 +++++++++-- 3 files changed, 52 insertions(+), 17 deletions(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 2636fa6..b0a7e24 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -143,3 +143,4 @@ Patches and Suggestions - Thomas Weißschuh @t-8ch - Jayson Vantuyl @kagato - Pengfei.X +- Kamil Madac diff --git a/requests/utils.py b/requests/utils.py index f92eed6..d785230 100644 --- a/requests/utils.py +++ b/requests/utils.py @@ -17,7 +17,8 @@ import os import platform import re import sys -import netaddr +import socket +import struct from . import __version__ from . import certs @@ -406,6 +407,39 @@ def requote_uri(uri): return quote(unquote_unreserved(uri), safe="!#$%&'()*+,/:;=?@[]~") +def address_in_network(ip,net): + '''This function allows you to check if on IP belogs to a Network''' + ipaddr = struct.unpack('=L', socket.inet_aton(ip))[0] + netaddr, bits = net.split('/') + netmask = struct.unpack('=L', socket.inet_aton(dotted_netmask(int(bits))))[0] + network = struct.unpack('=L', socket.inet_aton(netaddr))[0] & netmask + return (ipaddr & netmask) == (network & netmask) + + +def dotted_netmask(mask): + bits = 0xffffffff ^ (1 << 32 - mask) - 1 + return socket.inet_ntoa(struct.pack('>I', bits)) + + +def is_ipv4_address(string_ip): + try: + socket.inet_aton(string_ip) + except BaseException: + return False + return True + + +def is_ipv4_network(string_network): + if '/' in string_network: + try: + socket.inet_aton(string_network.split('/')[0]) + except OSError: + return False + else: + return False + return True + + def get_environ_proxies(url): """Return a dict of environment proxies.""" @@ -421,21 +455,12 @@ def get_environ_proxies(url): # the end of the netloc, both with and without the port. no_proxy = no_proxy.replace(' ', '').split(',') - ip = None - try: - ip = netaddr.IPAddress(netloc.split(':')[0]) - except netaddr.AddrFormatError: - pass - - if ip: + ip = netloc.split(':')[0] + if is_ipv4_address(ip): for proxy_ip in no_proxy: - proxy_ipaddress = None - try: - proxy_ipaddress = netaddr.IPNetwork(proxy_ip) - except (netaddr.AddrFormatError, ValueError): - continue - if proxy_ipaddress and ip in proxy_ipaddress: - return {} + if is_ipv4_network(proxy_ip): + if address_in_network(ip, proxy_ip): + return {} else: for host in no_proxy: if netloc.endswith(host) or netloc.split(':')[0].endswith(host): diff --git a/test_requests.py b/test_requests.py index cb91ade..396970a 100755 --- a/test_requests.py +++ b/test_requests.py @@ -913,11 +913,20 @@ class UtilsTestCase(unittest.TestCase): def test_get_environ_proxies_ip_ranges(self): """ Ensures that IP addresses are correctly matches with ranges in no_proxy variable """ from requests.utils import get_environ_proxies - os.environ['no_proxy'] = "127.0.0.1,localhost.localdomain,192.168.0.0/24,172.16.1.1" + os.environ['no_proxy'] = "192.168.0.0/24,127.0.0.1,localhost.localdomain,172.16.1.1" assert get_environ_proxies('http://192.168.0.1:5000/') == {} assert get_environ_proxies('http://192.168.0.1/') == {} assert get_environ_proxies('http://172.16.1.1/') == {} - assert get_environ_proxies('http://192.168.1.1:5000/') == {'no': os.environ['no_proxy']} + assert get_environ_proxies('http://172.16.1.1:5000/') == {} + assert get_environ_proxies('http://192.168.1.1:5000/') != {} + assert get_environ_proxies('http://192.168.1.1/') != {} + + def test_get_environ_proxies(self): + """ Ensures that IP addresses are correctly matches with ranges in no_proxy variable """ + from requests.utils import get_environ_proxies + os.environ['no_proxy'] = "127.0.0.1,localhost.localdomain,192.168.0.0/24,172.16.1.1" + assert get_environ_proxies('http://localhost.localdomain:5000/v1.0/') == {} + assert get_environ_proxies('http://www.requests.com/') != {} if __name__ == '__main__': unittest.main() -- 2.34.1