from itertools import product try: from urllib.parse import urljoin except ImportError: from urlparse import urljoin try: from urllib.parse import urlparse except ImportError: from urlparse import urlparse import csv import posixpath def remove_dot_segments(url): """ >>> remove_dot_segments('https://www.example.com/foo/bar/../../baz/bux/') 'https://www.example.com/baz/bux/' >>> remove_dot_segments('https://www.example.com/some/path/../file.ext') 'https://www.example.com/some/file.ext' """ parsed = urlparse(url) new_path = posixpath.normpath(parsed.path) if parsed.path.endswith('/'): # Fix missing trailing slash. # https://bugs.python.org/issue1707768 new_path += '/' if new_path.startswith('//'): new_path = new_path[1:] cleaned = parsed._replace(path=new_path) return cleaned.geturl() first_authorities = [ 'http://example.com@user:pass:7152', 'https://example.com', ] second_authorities = [ '', 'https://www.example.org', 'http://example.com@user:pass:1111', 'file://example.com', 'file://', ] first_paths = [ '', '/', '/foobar/bazz', 'foobar/bazz/', ] second_paths = [ '', '/', '/foo/bar', 'foo/bar/', './foo/../bar', 'foo/./.././bar', ] first_queries = ['', '?a=1', '?a=647&b=s564'] second_queries = ['', '?a=sdf', '?a=cvb&b=987'] fragments = ['', '#foo', '#bar'] additional_tests = [ { 'args': [ 'http://www.example.com/', '', ], 'expected': 'http://www.example.com/', }, { 'args': [ 'http://www.example.com/', 'foo', ], 'expected': 'http://www.example.com/foo', }, { 'args': [ 'http://www.example.com/', '/foo', ], 'expected': 'http://www.example.com/foo', }, { 'args': [ 'http://www.example.com/', '/foo/', ], 'expected': 'http://www.example.com/foo/', }, { 'args': [ 'http://www.example.com/', '/dir/page.html', ], 'expected': 'http://www.example.com/dir/page.html', }, { 'args': [ 'http://www.example.com/dir1/page2.html', '/dir/page.html', ], 'expected': 'http://www.example.com/dir/page.html', }, { 'args': [ 'http://www.example.com/dir1/page2.html', 'dir/page.html', ], 'expected': 'http://www.example.com/dir1/dir/page.html', }, { 'args': [ 'http://www.example.com/dir1/dir3/page.html', '../dir/page.html', ], 'expected': 'http://www.example.com/dir1/dir/page.html', }, ] with open('urls.csv', 'wt') as f: csvwriter = csv.writer(f, quotechar='"', quoting=csv.QUOTE_ALL) csvwriter.writerow(['first_url', 'second_url', 'expected']) for test in additional_tests: csvwriter.writerow([test['args'][0], test['args'][1], test['expected']]) for first_domain, second_domain in product(first_authorities, second_authorities): for first_path, second_path in product(first_paths, second_paths): for first_query, second_query in product(first_queries, second_queries): for first_fragment, second_fragment in product(fragments, fragments): if not first_path.startswith('/'): first_path = '/' + first_path first_url = first_domain + first_path + first_query + first_fragment if second_domain and not second_path.startswith('/'): second_path = '/' + second_path second_url = second_domain + second_path + second_query + second_fragment if first_url != second_url: expected_url = remove_dot_segments(urljoin(first_url, second_url)) csvwriter.writerow([first_url, second_url, expected_url])