comparison mercurial/url.py @ 49279:127d33e63d1a

branching: merge stable into default
author Raphaël Gomès <rgomes@octobus.net>
date Wed, 08 Jun 2022 15:46:04 +0200
parents 642e31cb55f0 51b07ac1991c
children 9f3edb305261
comparison
equal deleted inserted replaced
49275:c6a3243567b6 49279:127d33e63d1a
10 10
11 import base64 11 import base64
12 import socket 12 import socket
13 13
14 from .i18n import _ 14 from .i18n import _
15 from .pycompat import getattr
16 from . import ( 15 from . import (
17 encoding, 16 encoding,
18 error, 17 error,
19 httpconnection as httpconnectionmod, 18 httpconnection as httpconnectionmod,
20 keepalive, 19 keepalive,
196 195
197 class httpconnection(keepalive.HTTPConnection): 196 class httpconnection(keepalive.HTTPConnection):
198 # must be able to send big bundle as stream. 197 # must be able to send big bundle as stream.
199 send = _gen_sendfile(keepalive.HTTPConnection.send) 198 send = _gen_sendfile(keepalive.HTTPConnection.send)
200 199
201 def getresponse(self):
202 proxyres = getattr(self, 'proxyres', None)
203 if proxyres:
204 if proxyres.will_close:
205 self.close()
206 self.proxyres = None
207 return proxyres
208 return keepalive.HTTPConnection.getresponse(self)
209
210 200
211 # Large parts of this function have their origin from before Python 2.6 201 # Large parts of this function have their origin from before Python 2.6
212 # and could potentially be removed. 202 # and could potentially be removed.
213 def _generic_start_transaction(handler, h, req): 203 def _generic_start_transaction(handler, h, req):
214 tunnel_host = req._tunnel_host 204 tunnel_host = req._tunnel_host
253 version, status, reason = res._read_status() 243 version, status, reason = res._read_status()
254 if status != httplib.CONTINUE: 244 if status != httplib.CONTINUE:
255 break 245 break
256 # skip lines that are all whitespace 246 # skip lines that are all whitespace
257 list(iter(lambda: res.fp.readline().strip(), b'')) 247 list(iter(lambda: res.fp.readline().strip(), b''))
258 res.status = status 248
259 res.reason = reason.strip() 249 if status == 200:
260
261 if res.status == 200:
262 # skip lines until we find a blank line 250 # skip lines until we find a blank line
263 list(iter(res.fp.readline, b'\r\n')) 251 list(iter(res.fp.readline, b'\r\n'))
264 return True
265
266 if version == b'HTTP/1.0':
267 res.version = 10
268 elif version.startswith(b'HTTP/1.'):
269 res.version = 11
270 elif version == b'HTTP/0.9':
271 res.version = 9
272 else: 252 else:
273 raise httplib.UnknownProtocol(version) 253 self.close()
274 254 raise socket.error(
275 if res.version == 9: 255 "Tunnel connection failed: %d %s" % (status, reason.strip())
276 res.length = None 256 )
277 res.chunked = 0
278 res.will_close = 1
279 res.msg = httplib.HTTPMessage(stringio())
280 return False
281
282 res.msg = httplib.HTTPMessage(res.fp)
283 res.msg.fp = None
284
285 # are we using the chunked-style of transfer encoding?
286 trenc = res.msg.getheader(b'transfer-encoding')
287 if trenc and trenc.lower() == b"chunked":
288 res.chunked = 1
289 res.chunk_left = None
290 else:
291 res.chunked = 0
292
293 # will the connection close at the end of the response?
294 res.will_close = res._check_close()
295
296 # do we have a Content-Length?
297 # NOTE: RFC 2616, section 4.4, #3 says we ignore this if
298 # transfer-encoding is "chunked"
299 length = res.msg.getheader(b'content-length')
300 if length and not res.chunked:
301 try:
302 res.length = int(length)
303 except ValueError:
304 res.length = None
305 else:
306 if res.length < 0: # ignore nonsensical negative lengths
307 res.length = None
308 else:
309 res.length = None
310
311 # does the body have a fixed length? (of zero)
312 if (
313 status == httplib.NO_CONTENT
314 or status == httplib.NOT_MODIFIED
315 or 100 <= status < 200
316 or res._method == b'HEAD' # 1xx codes
317 ):
318 res.length = 0
319
320 # if the connection remains open, and we aren't using chunked, and
321 # a content-length was not provided, then assume that the connection
322 # WILL close.
323 if not res.will_close and not res.chunked and res.length is None:
324 res.will_close = 1
325
326 self.proxyres = res
327
328 return False
329 257
330 258
331 class httphandler(keepalive.HTTPHandler): 259 class httphandler(keepalive.HTTPHandler):
332 def http_open(self, req): 260 def http_open(self, req):
333 return self.do_open(httpconnection, req) 261 return self.do_open(httpconnection, req)