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