Subliminal update
This commit is contained in:
1 parent
5321037f08
commit
148e1940ac
85 files changed
+4375
-3420
No files matched your search
@@ -9,45 +9,51 @@ import socket
|
||||
|
||||
from socket import error as SocketError, timeout as SocketTimeout
|
||||
|
||||
try:
|
||||
from select import poll, POLLIN
|
||||
except ImportError: # Doesn't exist on OSX and other platforms
|
||||
from select import select
|
||||
poll = False
|
||||
|
||||
try: # Python 3
|
||||
from http.client import HTTPConnection, HTTPSConnection, HTTPException
|
||||
from http.client import HTTPConnection, HTTPException
|
||||
from http.client import HTTP_PORT, HTTPS_PORT
|
||||
except ImportError:
|
||||
from httplib import HTTPConnection, HTTPSConnection, HTTPException
|
||||
from httplib import HTTPConnection, HTTPException
|
||||
from httplib import HTTP_PORT, HTTPS_PORT
|
||||
|
||||
try: # Python 3
|
||||
from queue import Queue, Empty, Full
|
||||
from queue import LifoQueue, Empty, Full
|
||||
except ImportError:
|
||||
from Queue import Queue, Empty, Full
|
||||
from Queue import LifoQueue, Empty, Full
|
||||
|
||||
|
||||
try: # Compiled with SSL?
|
||||
HTTPSConnection = object
|
||||
BaseSSLError = None
|
||||
ssl = None
|
||||
|
||||
try: # Python 3
|
||||
from http.client import HTTPSConnection
|
||||
except ImportError:
|
||||
from httplib import HTTPSConnection
|
||||
|
||||
import ssl
|
||||
BaseSSLError = ssl.SSLError
|
||||
except ImportError:
|
||||
ssl = None
|
||||
BaseSSLError = None
|
||||
|
||||
except (ImportError, AttributeError):
|
||||
pass
|
||||
|
||||
|
||||
from .packages.ssl_match_hostname import match_hostname, CertificateError
|
||||
from .request import RequestMethods
|
||||
from .response import HTTPResponse
|
||||
from .exceptions import (SSLError,
|
||||
MaxRetryError,
|
||||
TimeoutError,
|
||||
HostChangedError,
|
||||
from .util import get_host, is_connection_dropped
|
||||
from .exceptions import (
|
||||
EmptyPoolError,
|
||||
HostChangedError,
|
||||
MaxRetryError,
|
||||
SSLError,
|
||||
TimeoutError,
|
||||
)
|
||||
|
||||
from .packages.ssl_match_hostname import match_hostname, CertificateError
|
||||
from .packages import six
|
||||
|
||||
|
||||
xrange = six.moves.xrange
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -59,6 +65,7 @@ port_by_scheme = {
|
||||
'https': HTTPS_PORT,
|
||||
}
|
||||
|
||||
|
||||
## Connection objects (extension of httplib)
|
||||
|
||||
class VerifiedHTTPSConnection(HTTPSConnection):
|
||||
@@ -94,6 +101,7 @@ class VerifiedHTTPSConnection(HTTPSConnection):
|
||||
if self.ca_certs:
|
||||
match_hostname(self.sock.getpeercert(), self.host)
|
||||
|
||||
|
||||
## Pool objects
|
||||
|
||||
class ConnectionPool(object):
|
||||
@@ -103,6 +111,7 @@ class ConnectionPool(object):
|
||||
"""
|
||||
|
||||
scheme = None
|
||||
QueueCls = LifoQueue
|
||||
|
||||
def __init__(self, host, port=None):
|
||||
self.host = host
|
||||
@@ -156,11 +165,11 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods):
|
||||
|
||||
def __init__(self, host, port=None, strict=False, timeout=None, maxsize=1,
|
||||
block=False, headers=None):
|
||||
self.host = host
|
||||
self.port = port
|
||||
super(HTTPConnectionPool, self).__init__(host, port)
|
||||
|
||||
self.strict = strict
|
||||
self.timeout = timeout
|
||||
self.pool = Queue(maxsize)
|
||||
self.pool = self.QueueCls(maxsize)
|
||||
self.block = block
|
||||
self.headers = headers or {}
|
||||
|
||||
@@ -198,7 +207,7 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods):
|
||||
conn = self.pool.get(block=self.block, timeout=timeout)
|
||||
|
||||
# If this is a persistent connection, check if it got disconnected
|
||||
if conn and conn.sock and is_connection_dropped(conn):
|
||||
if conn and is_connection_dropped(conn):
|
||||
log.info("Resetting dropped connection: %s" % self.host)
|
||||
conn.close()
|
||||
|
||||
@@ -242,9 +251,13 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods):
|
||||
timeout = self.timeout
|
||||
|
||||
conn.timeout = timeout # This only does anything in Py26+
|
||||
|
||||
conn.request(method, url, **httplib_request_kw)
|
||||
conn.sock.settimeout(timeout)
|
||||
|
||||
# Set timeout
|
||||
sock = getattr(conn, 'sock', False) # AppEngine doesn't have sock attr.
|
||||
if sock:
|
||||
sock.settimeout(timeout)
|
||||
|
||||
httplib_response = conn.getresponse()
|
||||
|
||||
log.debug("\"%s %s %s\" %s %s" %
|
||||
@@ -281,7 +294,7 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods):
|
||||
.. note::
|
||||
|
||||
More commonly, it's appropriate to use a convenience method provided
|
||||
by :class:`.RequestMethods`, such as :meth:`.request`.
|
||||
by :class:`.RequestMethods`, such as :meth:`request`.
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -468,7 +481,11 @@ class HTTPSConnectionPool(HTTPConnectionPool):
|
||||
log.info("Starting new HTTPS connection (%d): %s"
|
||||
% (self.num_connections, self.host))
|
||||
|
||||
if not ssl:
|
||||
if not ssl: # Platform-specific: Python compiled without +ssl
|
||||
if not HTTPSConnection or HTTPSConnection is object:
|
||||
raise SSLError("Can't connect to HTTPS URL because the SSL "
|
||||
"module is not available.")
|
||||
|
||||
return HTTPSConnection(host=self.host, port=self.port)
|
||||
|
||||
connection = VerifiedHTTPSConnection(host=self.host, port=self.port)
|
||||
@@ -477,87 +494,6 @@ class HTTPSConnectionPool(HTTPConnectionPool):
|
||||
return connection
|
||||
|
||||
|
||||
## Helpers
|
||||
|
||||
def make_headers(keep_alive=None, accept_encoding=None, user_agent=None,
|
||||
basic_auth=None):
|
||||
"""
|
||||
Shortcuts for generating request headers.
|
||||
|
||||
:param keep_alive:
|
||||
If ``True``, adds 'connection: keep-alive' header.
|
||||
|
||||
:param accept_encoding:
|
||||
Can be a boolean, list, or string.
|
||||
``True`` translates to 'gzip,deflate'.
|
||||
List will get joined by comma.
|
||||
String will be used as provided.
|
||||
|
||||
:param user_agent:
|
||||
String representing the user-agent you want, such as
|
||||
"python-urllib3/0.6"
|
||||
|
||||
:param basic_auth:
|
||||
Colon-separated username:password string for 'authorization: basic ...'
|
||||
auth header.
|
||||
|
||||
Example: ::
|
||||
|
||||
>>> make_headers(keep_alive=True, user_agent="Batman/1.0")
|
||||
{'connection': 'keep-alive', 'user-agent': 'Batman/1.0'}
|
||||
>>> make_headers(accept_encoding=True)
|
||||
{'accept-encoding': 'gzip,deflate'}
|
||||
"""
|
||||
headers = {}
|
||||
if accept_encoding:
|
||||
if isinstance(accept_encoding, str):
|
||||
pass
|
||||
elif isinstance(accept_encoding, list):
|
||||
accept_encoding = ','.join(accept_encoding)
|
||||
else:
|
||||
accept_encoding = 'gzip,deflate'
|
||||
headers['accept-encoding'] = accept_encoding
|
||||
|
||||
if user_agent:
|
||||
headers['user-agent'] = user_agent
|
||||
|
||||
if keep_alive:
|
||||
headers['connection'] = 'keep-alive'
|
||||
|
||||
if basic_auth:
|
||||
headers['authorization'] = 'Basic ' + \
|
||||
basic_auth.encode('base64').strip()
|
||||
|
||||
return headers
|
||||
|
||||
|
||||
def get_host(url):
|
||||
"""
|
||||
Given a url, return its scheme, host and port (None if it's not there).
|
||||
|
||||
For example: ::
|
||||
|
||||
>>> get_host('http://google.com/mail/')
|
||||
('http', 'google.com', None)
|
||||
>>> get_host('google.com:80')
|
||||
('http', 'google.com', 80)
|
||||
"""
|
||||
# This code is actually similar to urlparse.urlsplit, but much
|
||||
# simplified for our needs.
|
||||
port = None
|
||||
scheme = 'http'
|
||||
if '://' in url:
|
||||
scheme, url = url.split('://', 1)
|
||||
if '/' in url:
|
||||
url, _path = url.split('/', 1)
|
||||
if '@' in url:
|
||||
_auth, url = url.split('@', 1)
|
||||
if ':' in url:
|
||||
url, port = url.split(':', 1)
|
||||
port = int(port)
|
||||
return scheme, url, port
|
||||
|
||||
|
||||
def connection_from_url(url, **kw):
|
||||
"""
|
||||
Given a url, return an :class:`.ConnectionPool` instance of its host.
|
||||
@@ -583,22 +519,3 @@ def connection_from_url(url, **kw):
|
||||
return HTTPSConnectionPool(host, port=port, **kw)
|
||||
else:
|
||||
return HTTPConnectionPool(host, port=port, **kw)
|
||||
|
||||
|
||||
def is_connection_dropped(conn):
|
||||
"""
|
||||
Returns True if the connection is dropped and should be closed.
|
||||
|
||||
:param conn:
|
||||
``HTTPConnection`` object.
|
||||
"""
|
||||
if not poll:
|
||||
return select([conn.sock], [], [], 0.0)[0]
|
||||
|
||||
# This version is better on platforms that support it.
|
||||
p = poll()
|
||||
p.register(conn.sock, POLLIN)
|
||||
for (fno, ev) in p.poll(0.0):
|
||||
if fno == conn.sock.fileno():
|
||||
# Either data is buffered (bad), or the connection is dropped.
|
||||
return True
|
||||
Reference in new issue
Block a user