comparison mercurial/url.py @ 41710:4028897dfa05

url: always use str for proxy configuration 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. Differential Revision: https://phab.mercurial-scm.org/D5952
author Gregory Szorc <gregory.szorc@gmail.com>
date Fri, 15 Feb 2019 13:16:07 -0800
parents d20f1594ff4a
children 544035846830
comparison
equal deleted inserted replaced
41709:97e2442a4595 41710:4028897dfa05
129 if ui.configbool("http_proxy", "always"): 129 if ui.configbool("http_proxy", "always"):
130 self.no_list = [] 130 self.no_list = []
131 else: 131 else:
132 self.no_list = no_list 132 self.no_list = no_list
133 133
134 proxyurl = bytes(proxy) 134 # Keys and values need to be str because the standard library
135 proxies = {'http': proxyurl, 'https': proxyurl} 135 # expects them to be.
136 ui.debug('proxying through %s\n' % util.hidepassword(proxyurl)) 136 proxyurl = str(proxy)
137 proxies = {r'http': proxyurl, r'https': proxyurl}
138 ui.debug('proxying through %s\n' % util.hidepassword(bytes(proxy)))
137 else: 139 else:
138 proxies = {} 140 proxies = {}
139 141
140 urlreq.proxyhandler.__init__(self, proxies) 142 urlreq.proxyhandler.__init__(self, proxies)
141 self.ui = ui 143 self.ui = ui
142 144
143 def proxy_open(self, req, proxy, type_): 145 def proxy_open(self, req, proxy, type_):
144 host = urllibcompat.gethost(req).split(':')[0] 146 host = pycompat.bytesurl(urllibcompat.gethost(req)).split(':')[0]
145 for e in self.no_list: 147 for e in self.no_list:
146 if host == e: 148 if host == e:
147 return None 149 return None
148 if e.startswith('*.') and host.endswith(e[2:]): 150 if e.startswith('*.') and host.endswith(e[2:]):
149 return None 151 return None
182 # Large parts of this function have their origin from before Python 2.6 184 # Large parts of this function have their origin from before Python 2.6
183 # and could potentially be removed. 185 # and could potentially be removed.
184 def _generic_start_transaction(handler, h, req): 186 def _generic_start_transaction(handler, h, req):
185 tunnel_host = req._tunnel_host 187 tunnel_host = req._tunnel_host
186 if tunnel_host: 188 if tunnel_host:
187 if tunnel_host[:7] not in ['http://', 'https:/']: 189 if tunnel_host[:7] not in [r'http://', r'https:/']:
188 tunnel_host = 'https://' + tunnel_host 190 tunnel_host = r'https://' + tunnel_host
189 new_tunnel = True 191 new_tunnel = True
190 else: 192 else:
191 tunnel_host = urllibcompat.getselector(req) 193 tunnel_host = urllibcompat.getselector(req)
192 new_tunnel = False 194 new_tunnel = False
193 195
194 if new_tunnel or tunnel_host == urllibcompat.getfullurl(req): # has proxy 196 if new_tunnel or tunnel_host == urllibcompat.getfullurl(req): # has proxy
195 u = util.url(tunnel_host) 197 u = util.url(pycompat.bytesurl(tunnel_host))
196 if new_tunnel or u.scheme == 'https': # only use CONNECT for HTTPS 198 if new_tunnel or u.scheme == 'https': # only use CONNECT for HTTPS
197 h.realhostport = ':'.join([u.host, (u.port or '443')]) 199 h.realhostport = ':'.join([u.host, (u.port or '443')])
198 h.headers = req.headers.copy() 200 h.headers = req.headers.copy()
199 h.headers.update(handler.parent.addheaders) 201 h.headers.update(handler.parent.addheaders)
200 return 202 return
203 h.headers = None 205 h.headers = None
204 206
205 def _generic_proxytunnel(self): 207 def _generic_proxytunnel(self):
206 proxyheaders = dict( 208 proxyheaders = dict(
207 [(x, self.headers[x]) for x in self.headers 209 [(x, self.headers[x]) for x in self.headers
208 if x.lower().startswith('proxy-')]) 210 if x.lower().startswith(r'proxy-')])
209 self.send('CONNECT %s HTTP/1.0\r\n' % self.realhostport) 211 self.send('CONNECT %s HTTP/1.0\r\n' % self.realhostport)
210 for header in proxyheaders.iteritems(): 212 for header in proxyheaders.iteritems():
211 self.send('%s: %s\r\n' % header) 213 self.send('%s: %s\r\n' % header)
212 self.send('\r\n') 214 self.send('\r\n')
213 215