D5952: url: always use str for proxy configuration

indygreg (Gregory Szorc) phabricator at mercurial-scm.org
Tue Feb 12 22:37:28 UTC 2019


indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Previously, proxies didn't work on Python 3 for various reasons.
  
  First, the keys to the "proxies" dict are fed into a
  `setattr(self, "%s_open", ...)` call and passing bytestrings
  results in setting an oddly named attribute due to the b''
  in %s formatting. This resulted in "http_open" and "https_open"
  not being properly overridden and proxies not being used.
  
  Second, the standard library was expecting proxy URLs to be
  str. And various operations (including our custom code in
  url.py) would fail to account for the str/bytes mismatch.
  
  This commit normalizes everything to str and adjusts our
  proxy code in url.py to account for the presence of str
  on Python 3.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5952

AFFECTED FILES
  mercurial/url.py

CHANGE DETAILS

diff --git a/mercurial/url.py b/mercurial/url.py
--- a/mercurial/url.py
+++ b/mercurial/url.py
@@ -131,17 +131,19 @@
             else:
                 self.no_list = no_list
 
-            proxyurl = bytes(proxy)
-            proxies = {'http': proxyurl, 'https': proxyurl}
-            ui.debug('proxying through %s\n' % util.hidepassword(proxyurl))
+            # Keys and values need to be str because the standard library
+            # expects them to be.
+            proxyurl = str(proxy)
+            proxies = {r'http': proxyurl, r'https': proxyurl}
+            ui.debug('proxying through %s\n' % util.hidepassword(bytes(proxy)))
         else:
             proxies = {}
 
         urlreq.proxyhandler.__init__(self, proxies)
         self.ui = ui
 
     def proxy_open(self, req, proxy, type_):
-        host = urllibcompat.gethost(req).split(':')[0]
+        host = pycompat.bytesurl(urllibcompat.gethost(req)).split(':')[0]
         for e in self.no_list:
             if host == e:
                 return None
@@ -184,15 +186,15 @@
 def _generic_start_transaction(handler, h, req):
     tunnel_host = req._tunnel_host
     if tunnel_host:
-        if tunnel_host[:7] not in ['http://', 'https:/']:
-            tunnel_host = 'https://' + tunnel_host
+        if tunnel_host[:7] not in [r'http://', r'https:/']:
+            tunnel_host = r'https://' + tunnel_host
         new_tunnel = True
     else:
         tunnel_host = urllibcompat.getselector(req)
         new_tunnel = False
 
     if new_tunnel or tunnel_host == urllibcompat.getfullurl(req): # has proxy
-        u = util.url(tunnel_host)
+        u = util.url(pycompat.bytesurl(tunnel_host))
         if new_tunnel or u.scheme == 'https': # only use CONNECT for HTTPS
             h.realhostport = ':'.join([u.host, (u.port or '443')])
             h.headers = req.headers.copy()



To: indygreg, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list