117 lines
3.9 KiB
Python
117 lines
3.9 KiB
Python
import sys
|
|
import socket
|
|
|
|
try:
|
|
# Python 3
|
|
from urllib.error import URLError
|
|
except ImportError:
|
|
# Python 2
|
|
from urllib2 import URLError
|
|
from urllib import addinfourl
|
|
|
|
from ..console_write import console_write
|
|
|
|
|
|
class PersistentHandler:
|
|
connection = None
|
|
use_count = 0
|
|
|
|
def close(self):
|
|
if self.connection:
|
|
if self._debuglevel == 5:
|
|
s = '' if self.use_count == 1 else 's'
|
|
console_write(u"Urllib %s Debug General" % self.connection._debug_protocol, True)
|
|
console_write(u" Closing connection to %s on port %s after %s request%s" % (
|
|
self.connection.host, self.connection.port, self.use_count, s))
|
|
self.connection.close()
|
|
self.connection = None
|
|
self.use_count = 0
|
|
|
|
def do_open(self, http_class, req):
|
|
# Large portions from Python 3.3 Lib/urllib/request.py and
|
|
# Python 2.6 Lib/urllib2.py
|
|
|
|
if sys.version_info >= (3,):
|
|
host = req.host
|
|
else:
|
|
host = req.get_host()
|
|
|
|
if not host:
|
|
raise URLError('no host given')
|
|
|
|
if self.connection and self.connection.host != host:
|
|
self.close()
|
|
|
|
# Re-use the connection if possible
|
|
self.use_count += 1
|
|
if not self.connection:
|
|
h = http_class(host, timeout=req.timeout)
|
|
else:
|
|
h = self.connection
|
|
if self._debuglevel == 5:
|
|
console_write(u"Urllib %s Debug General" % h._debug_protocol, True)
|
|
console_write(u" Re-using connection to %s on port %s for request #%s" % (
|
|
h.host, h.port, self.use_count))
|
|
|
|
if sys.version_info >= (3,):
|
|
headers = dict(req.unredirected_hdrs)
|
|
headers.update(dict((k, v) for k, v in req.headers.items()
|
|
if k not in headers))
|
|
headers = dict((name.title(), val) for name, val in headers.items())
|
|
|
|
else:
|
|
h.set_debuglevel(self._debuglevel)
|
|
|
|
headers = dict(req.headers)
|
|
headers.update(req.unredirected_hdrs)
|
|
headers = dict(
|
|
(name.title(), val) for name, val in headers.items())
|
|
|
|
if req._tunnel_host and not self.connection:
|
|
tunnel_headers = {}
|
|
proxy_auth_hdr = "Proxy-Authorization"
|
|
if proxy_auth_hdr in headers:
|
|
tunnel_headers[proxy_auth_hdr] = headers[proxy_auth_hdr]
|
|
del headers[proxy_auth_hdr]
|
|
|
|
if sys.version_info >= (3,):
|
|
h.set_tunnel(req._tunnel_host, headers=tunnel_headers)
|
|
else:
|
|
h._set_tunnel(req._tunnel_host, headers=tunnel_headers)
|
|
|
|
try:
|
|
if sys.version_info >= (3,):
|
|
h.request(req.get_method(), req.selector, req.data, headers)
|
|
else:
|
|
h.request(req.get_method(), req.get_selector(), req.data, headers)
|
|
except socket.error as err: # timeout error
|
|
h.close()
|
|
raise URLError(err)
|
|
else:
|
|
r = h.getresponse()
|
|
|
|
# Keep the connection around for re-use
|
|
if r.is_keep_alive():
|
|
self.connection = h
|
|
else:
|
|
if self._debuglevel == 5:
|
|
s = '' if self.use_count == 1 else 's'
|
|
console_write(u"Urllib %s Debug General" % h._debug_protocol, True)
|
|
console_write(u" Closing connection to %s on port %s after %s request%s" % (
|
|
h.host, h.port, self.use_count, s))
|
|
self.use_count = 0
|
|
self.connection = None
|
|
|
|
if sys.version_info >= (3,):
|
|
r.url = req.get_full_url()
|
|
r.msg = r.reason
|
|
return r
|
|
|
|
r.recv = r.read
|
|
fp = socket._fileobject(r, close=True)
|
|
|
|
resp = addinfourl(fp, r.msg, req.get_full_url())
|
|
resp.code = r.status
|
|
resp.msg = r.reason
|
|
return resp
|