mercurial/httpclient/__init__.py
changeset 27601 1ad9da968a2e
parent 25660 328739ea70c3
child 28861 86db5cb55d46
equal deleted inserted replaced
27600:cfb26146a8cd 27601:1ad9da968a2e
    34   * supports keepalives natively
    34   * supports keepalives natively
    35   * uses select() to block for incoming data
    35   * uses select() to block for incoming data
    36   * notices when the server responds early to a request
    36   * notices when the server responds early to a request
    37   * implements ssl inline instead of in a different class
    37   * implements ssl inline instead of in a different class
    38 """
    38 """
       
    39 from __future__ import absolute_import
    39 
    40 
    40 # Many functions in this file have too many arguments.
    41 # Many functions in this file have too many arguments.
    41 # pylint: disable=R0913
    42 # pylint: disable=R0913
    42 
    43 
    43 import cStringIO
    44 import cStringIO
    46 import logging
    47 import logging
    47 import rfc822
    48 import rfc822
    48 import select
    49 import select
    49 import socket
    50 import socket
    50 
    51 
    51 import _readers
    52 from . import (
    52 import socketutil
    53     _readers,
       
    54     socketutil,
       
    55     )
    53 
    56 
    54 logger = logging.getLogger(__name__)
    57 logger = logging.getLogger(__name__)
    55 
    58 
    56 __all__ = ['HTTPConnection', 'HTTPResponse']
    59 __all__ = ['HTTPConnection', 'HTTPResponse']
    57 
    60 
   121     def _close(self):
   124     def _close(self):
   122         if self._reader is not None:
   125         if self._reader is not None:
   123             # We're a friend of the reader class here.
   126             # We're a friend of the reader class here.
   124             # pylint: disable=W0212
   127             # pylint: disable=W0212
   125             self._reader._close()
   128             self._reader._close()
       
   129 
       
   130     def getheader(self, header, default=None):
       
   131         return self.headers.getheader(header, default=default)
       
   132 
       
   133     def getheaders(self):
       
   134         return self.headers.items()
   126 
   135 
   127     def readline(self):
   136     def readline(self):
   128         """Read a single line from the response body.
   137         """Read a single line from the response body.
   129 
   138 
   130         This may block until either a line ending is found or the
   139         This may block until either a line ending is found or the
   277         self.headers = headers
   286         self.headers = headers
   278         # We're a friend of the reader class here.
   287         # We're a friend of the reader class here.
   279         # pylint: disable=W0212
   288         # pylint: disable=W0212
   280         self._load_response = self._reader._load
   289         self._load_response = self._reader._load
   281 
   290 
       
   291 def _foldheaders(headers):
       
   292     """Given some headers, rework them so we can safely overwrite values.
       
   293 
       
   294     >>> _foldheaders({'Accept-Encoding': 'wat'})
       
   295     {'accept-encoding': ('Accept-Encoding', 'wat')}
       
   296     """
       
   297     return dict((k.lower(), (k, v)) for k, v in headers.iteritems())
       
   298 
   282 
   299 
   283 class HTTPConnection(object):
   300 class HTTPConnection(object):
   284     """Connection to a single http server.
   301     """Connection to a single http server.
   285 
   302 
   286     Supports 100-continue and keepalives natively. Uses select() for
   303     Supports 100-continue and keepalives natively. Uses select() for
   290     response_class = HTTPResponse
   307     response_class = HTTPResponse
   291 
   308 
   292     def __init__(self, host, port=None, use_ssl=None, ssl_validator=None,
   309     def __init__(self, host, port=None, use_ssl=None, ssl_validator=None,
   293                  timeout=TIMEOUT_DEFAULT,
   310                  timeout=TIMEOUT_DEFAULT,
   294                  continue_timeout=TIMEOUT_ASSUME_CONTINUE,
   311                  continue_timeout=TIMEOUT_ASSUME_CONTINUE,
   295                  proxy_hostport=None, ssl_wrap_socket=None, **ssl_opts):
   312                  proxy_hostport=None, proxy_headers=None,
       
   313                  ssl_wrap_socket=None, **ssl_opts):
   296         """Create a new HTTPConnection.
   314         """Create a new HTTPConnection.
   297 
   315 
   298         Args:
   316         Args:
   299           host: The host to which we'll connect.
   317           host: The host to which we'll connect.
   300           port: Optional. The port over which we'll connect. Default 80 for
   318           port: Optional. The port over which we'll connect. Default 80 for
   305           timeout: Optional. Connection timeout, default is TIMEOUT_DEFAULT.
   323           timeout: Optional. Connection timeout, default is TIMEOUT_DEFAULT.
   306           continue_timeout: Optional. Timeout for waiting on an expected
   324           continue_timeout: Optional. Timeout for waiting on an expected
   307                    "100 Continue" response. Default is TIMEOUT_ASSUME_CONTINUE.
   325                    "100 Continue" response. Default is TIMEOUT_ASSUME_CONTINUE.
   308           proxy_hostport: Optional. Tuple of (host, port) to use as an http
   326           proxy_hostport: Optional. Tuple of (host, port) to use as an http
   309                        proxy for the connection. Default is to not use a proxy.
   327                        proxy for the connection. Default is to not use a proxy.
       
   328           proxy_headers: Optional dict of header keys and values to send to
       
   329                          a proxy when using CONNECT. For compatibility with
       
   330                          httplib, the Proxy-Authorization header may be
       
   331                          specified in headers for request(), which will clobber
       
   332                          any such header specified here if specified. Providing
       
   333                          this option and not proxy_hostport will raise an
       
   334                          ValueError.
   310           ssl_wrap_socket: Optional function to use for wrapping
   335           ssl_wrap_socket: Optional function to use for wrapping
   311             sockets. If unspecified, the one from the ssl module will
   336             sockets. If unspecified, the one from the ssl module will
   312             be used if available, or something that's compatible with
   337             be used if available, or something that's compatible with
   313             it if on a Python older than 2.6.
   338             it if on a Python older than 2.6.
   314 
   339 
   328             use_ssl = False
   353             use_ssl = False
   329             port = 80
   354             port = 80
   330         elif use_ssl is None:
   355         elif use_ssl is None:
   331             use_ssl = (port == 443)
   356             use_ssl = (port == 443)
   332         elif port is None:
   357         elif port is None:
   333             if use_ssl:
   358             port = (use_ssl and 443 or 80)
   334                 port = 443
       
   335             else:
       
   336                 port = 80
       
   337         self.port = port
   359         self.port = port
   338         if use_ssl and not socketutil.have_ssl:
   360         if use_ssl and not socketutil.have_ssl:
   339             raise Exception('ssl requested but unavailable on this Python')
   361             raise Exception('ssl requested but unavailable on this Python')
   340         self.ssl = use_ssl
   362         self.ssl = use_ssl
   341         self.ssl_opts = ssl_opts
   363         self.ssl_opts = ssl_opts
   344         self.sock = None
   366         self.sock = None
   345         self._current_response = None
   367         self._current_response = None
   346         self._current_response_taken = False
   368         self._current_response_taken = False
   347         if proxy_hostport is None:
   369         if proxy_hostport is None:
   348             self._proxy_host = self._proxy_port = None
   370             self._proxy_host = self._proxy_port = None
       
   371             if proxy_headers:
       
   372                 raise ValueError(
       
   373                     'proxy_headers may not be specified unless '
       
   374                     'proxy_hostport is also specified.')
       
   375             else:
       
   376                 self._proxy_headers = {}
   349         else:
   377         else:
   350             self._proxy_host, self._proxy_port = proxy_hostport
   378             self._proxy_host, self._proxy_port = proxy_hostport
       
   379             self._proxy_headers = _foldheaders(proxy_headers or {})
   351 
   380 
   352         self.timeout = timeout
   381         self.timeout = timeout
   353         self.continue_timeout = continue_timeout
   382         self.continue_timeout = continue_timeout
   354 
   383 
   355     def _connect(self):
   384     def _connect(self, proxy_headers):
   356         """Connect to the host and port specified in __init__."""
   385         """Connect to the host and port specified in __init__."""
   357         if self.sock:
   386         if self.sock:
   358             return
   387             return
   359         if self._proxy_host is not None:
   388         if self._proxy_host is not None:
   360             logger.info('Connecting to http proxy %s:%s',
   389             logger.info('Connecting to http proxy %s:%s',
   361                         self._proxy_host, self._proxy_port)
   390                         self._proxy_host, self._proxy_port)
   362             sock = socketutil.create_connection((self._proxy_host,
   391             sock = socketutil.create_connection((self._proxy_host,
   363                                                  self._proxy_port))
   392                                                  self._proxy_port))
   364             if self.ssl:
   393             if self.ssl:
   365                 # TODO proxy header support
       
   366                 data = self._buildheaders('CONNECT', '%s:%d' % (self.host,
   394                 data = self._buildheaders('CONNECT', '%s:%d' % (self.host,
   367                                                                 self.port),
   395                                                                 self.port),
   368                                           {}, HTTP_VER_1_0)
   396                                           proxy_headers, HTTP_VER_1_0)
   369                 sock.send(data)
   397                 sock.send(data)
   370                 sock.setblocking(0)
   398                 sock.setblocking(0)
   371                 r = self.response_class(sock, self.timeout, 'CONNECT')
   399                 r = self.response_class(sock, self.timeout, 'CONNECT')
   372                 timeout_exc = HTTPTimeoutException(
   400                 timeout_exc = HTTPTimeoutException(
   373                     'Timed out waiting for CONNECT response from proxy')
   401                     'Timed out waiting for CONNECT response from proxy')
   466                     self._current_response = None
   494                     self._current_response = None
   467                     return False
   495                     return False
   468             return True
   496             return True
   469         return False
   497         return False
   470 
   498 
   471     def _reconnect(self, where):
   499     def _reconnect(self, where, pheaders):
   472         logger.info('reconnecting during %s', where)
   500         logger.info('reconnecting during %s', where)
   473         self.close()
   501         self.close()
   474         self._connect()
   502         self._connect(pheaders)
   475 
   503 
   476     def request(self, method, path, body=None, headers={},
   504     def request(self, method, path, body=None, headers={},
   477                 expect_continue=False):
   505                 expect_continue=False):
   478         """Send a request to the server.
   506         """Send a request to the server.
   479 
   507 
   490                 'current response is read!')
   518                 'current response is read!')
   491         self._current_response_taken = False
   519         self._current_response_taken = False
   492 
   520 
   493         logger.info('sending %s request for %s to %s on port %s',
   521         logger.info('sending %s request for %s to %s on port %s',
   494                     method, path, self.host, self.port)
   522                     method, path, self.host, self.port)
   495         hdrs = dict((k.lower(), (k, v)) for k, v in headers.iteritems())
   523         hdrs = _foldheaders(headers)
   496         if hdrs.get('expect', ('', ''))[1].lower() == '100-continue':
   524         if hdrs.get('expect', ('', ''))[1].lower() == '100-continue':
   497             expect_continue = True
   525             expect_continue = True
   498         elif expect_continue:
   526         elif expect_continue:
   499             hdrs['expect'] = ('Expect', '100-Continue')
   527             hdrs['expect'] = ('Expect', '100-Continue')
       
   528         # httplib compatibility: if the user specified a
       
   529         # proxy-authorization header, that's actually intended for a
       
   530         # proxy CONNECT action, not the real request, but only if
       
   531         # we're going to use a proxy.
       
   532         pheaders = dict(self._proxy_headers)
       
   533         if self._proxy_host and self.ssl:
       
   534             pa = hdrs.pop('proxy-authorization', None)
       
   535             if pa is not None:
       
   536                 pheaders['proxy-authorization'] = pa
   500 
   537 
   501         chunked = False
   538         chunked = False
   502         if body and HDR_CONTENT_LENGTH not in hdrs:
   539         if body and HDR_CONTENT_LENGTH not in hdrs:
   503             if getattr(body, '__len__', False):
   540             if getattr(body, '__len__', False):
   504                 hdrs[HDR_CONTENT_LENGTH] = (HDR_CONTENT_LENGTH, len(body))
   541                 hdrs[HDR_CONTENT_LENGTH] = (HDR_CONTENT_LENGTH, len(body))
   511 
   548 
   512         # If we're reusing the underlying socket, there are some
   549         # If we're reusing the underlying socket, there are some
   513         # conditions where we'll want to retry, so make a note of the
   550         # conditions where we'll want to retry, so make a note of the
   514         # state of self.sock
   551         # state of self.sock
   515         fresh_socket = self.sock is None
   552         fresh_socket = self.sock is None
   516         self._connect()
   553         self._connect(pheaders)
   517         outgoing_headers = self._buildheaders(
   554         outgoing_headers = self._buildheaders(
   518             method, path, hdrs, self.http_version)
   555             method, path, hdrs, self.http_version)
   519         response = None
   556         response = None
   520         first = True
   557         first = True
   521 
   558 
   586                             # after getting a really large response
   623                             # after getting a really large response
   587                             # from the server.
   624                             # from the server.
   588                             logger.info(
   625                             logger.info(
   589                                 'Connection appeared closed in read on first'
   626                                 'Connection appeared closed in read on first'
   590                                 ' request loop iteration, will retry.')
   627                                 ' request loop iteration, will retry.')
   591                             self._reconnect('read')
   628                             self._reconnect('read', pheaders)
   592                             continue
   629                             continue
   593                         else:
   630                         else:
   594                             # We didn't just send the first data hunk,
   631                             # We didn't just send the first data hunk,
   595                             # and either have a partial response or no
   632                             # and either have a partial response or no
   596                             # response at all. There's really nothing
   633                             # response at all. There's really nothing
   643                     if e[0] == errno.EWOULDBLOCK or e[0] == errno.EAGAIN:
   680                     if e[0] == errno.EWOULDBLOCK or e[0] == errno.EAGAIN:
   644                         continue
   681                         continue
   645                     elif (e[0] not in (errno.ECONNRESET, errno.EPIPE)
   682                     elif (e[0] not in (errno.ECONNRESET, errno.EPIPE)
   646                           and not first):
   683                           and not first):
   647                         raise
   684                         raise
   648                     self._reconnect('write')
   685                     self._reconnect('write', pheaders)
   649                     amt = self.sock.send(out)
   686                     amt = self.sock.send(out)
   650                 logger.debug('sent %d', amt)
   687                 logger.debug('sent %d', amt)
   651                 first = False
   688                 first = False
   652                 if out is body:
   689                 if out is body:
   653                     body = out[amt:]
   690                     body = out[amt:]
   662                 if not response._select():
   699                 if not response._select():
   663                     # This means the response failed to get any response
   700                     # This means the response failed to get any response
   664                     # data at all, and in all probability the socket was
   701                     # data at all, and in all probability the socket was
   665                     # closed before the server even saw our request. Try
   702                     # closed before the server even saw our request. Try
   666                     # the request again on a fresh socket.
   703                     # the request again on a fresh socket.
   667                     logging.debug('response._select() failed during request().'
   704                     logger.debug('response._select() failed during request().'
   668                                   ' Assuming request needs to be retried.')
   705                                  ' Assuming request needs to be retried.')
   669                     self.sock = None
   706                     self.sock = None
   670                     # Call this method explicitly to re-try the
   707                     # Call this method explicitly to re-try the
   671                     # request. We don't use self.request() because
   708                     # request. We don't use self.request() because
   672                     # some tools (notably Mercurial) expect to be able
   709                     # some tools (notably Mercurial) expect to be able
   673                     # to subclass and redefine request(), and they
   710                     # to subclass and redefine request(), and they