Mercurial > public > mercurial-scm > hg
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 |