Merge pull request #1385 from elpollodiablo/master
Change http_handler to use requests instead of urllib3
This commit is contained in:
@@ -19,11 +19,11 @@ from __future__ import unicode_literals
|
|||||||
from future.builtins import object
|
from future.builtins import object
|
||||||
from future.builtins import str
|
from future.builtins import str
|
||||||
|
|
||||||
from functools import partial
|
|
||||||
from multiprocessing.dummy import Pool as ThreadPool
|
from multiprocessing.dummy import Pool as ThreadPool
|
||||||
from future.moves.urllib.parse import urljoin
|
from future.moves.urllib.parse import urljoin
|
||||||
|
|
||||||
import certifi
|
import certifi
|
||||||
|
import requests
|
||||||
import urllib3
|
import urllib3
|
||||||
|
|
||||||
import plexpy
|
import plexpy
|
||||||
@@ -41,6 +41,7 @@ class HTTPHandler(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, urls, headers=None, token=None, timeout=10, ssl_verify=True, silent=False):
|
def __init__(self, urls, headers=None, token=None, timeout=10, ssl_verify=True, silent=False):
|
||||||
|
self._valid_request_types = {'GET', 'POST', 'PUT', 'DELETE'}
|
||||||
self._silent = silent
|
self._silent = silent
|
||||||
|
|
||||||
if isinstance(urls, str):
|
if isinstance(urls, str):
|
||||||
@@ -51,24 +52,34 @@ class HTTPHandler(object):
|
|||||||
if headers:
|
if headers:
|
||||||
self.headers = headers
|
self.headers = headers
|
||||||
else:
|
else:
|
||||||
self.headers = {'X-Plex-Product': plexpy.common.PRODUCT,
|
self.headers = {
|
||||||
'X-Plex-Version': plexpy.common.RELEASE,
|
'X-Plex-Product': plexpy.common.PRODUCT,
|
||||||
'X-Plex-Client-Identifier': plexpy.CONFIG.PMS_UUID,
|
'X-Plex-Version': plexpy.common.RELEASE,
|
||||||
'X-Plex-Platform': plexpy.common.PLATFORM,
|
'X-Plex-Client-Identifier': plexpy.CONFIG.PMS_UUID,
|
||||||
'X-Plex-Platform-Version': plexpy.common.PLATFORM_RELEASE,
|
'X-Plex-Platform': plexpy.common.PLATFORM,
|
||||||
'X-Plex-Device': '{} {}'.format(plexpy.common.PLATFORM,
|
'X-Plex-Platform-Version': plexpy.common.PLATFORM_RELEASE,
|
||||||
plexpy.common.PLATFORM_RELEASE),
|
'X-Plex-Device': '{} {}'.format(plexpy.common.PLATFORM,
|
||||||
'X-Plex-Device-Name': plexpy.common.PLATFORM_DEVICE_NAME
|
plexpy.common.PLATFORM_RELEASE),
|
||||||
}
|
'X-Plex-Device-Name': plexpy.common.PLATFORM_DEVICE_NAME
|
||||||
|
}
|
||||||
|
|
||||||
self.token = token
|
self.token = token
|
||||||
if self.token:
|
if self.token:
|
||||||
self.headers['X-Plex-Token'] = self.token
|
self.headers['X-Plex-Token'] = self.token
|
||||||
|
|
||||||
|
self._session = requests.Session()
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
self.ssl_verify = ssl_verify
|
self.ssl_verify = certifi.where() if ssl_verify else False
|
||||||
|
if not self.ssl_verify:
|
||||||
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||||
|
|
||||||
self.valid_request_types = ('GET', 'POST', 'PUT', 'DELETE')
|
self.uri = None
|
||||||
|
self.data = None
|
||||||
|
self.request_type = 'GET'
|
||||||
|
self.output_format = 'raw'
|
||||||
|
self.return_type = False
|
||||||
|
self.callback = None
|
||||||
|
self.request_kwargs = {}
|
||||||
|
|
||||||
def make_request(self,
|
def make_request(self,
|
||||||
uri=None,
|
uri=None,
|
||||||
@@ -96,7 +107,7 @@ class HTTPHandler(object):
|
|||||||
self.timeout = timeout or self.timeout
|
self.timeout = timeout or self.timeout
|
||||||
self.request_kwargs = request_kwargs
|
self.request_kwargs = request_kwargs
|
||||||
|
|
||||||
if self.request_type not in self.valid_request_types:
|
if self.request_type not in self._valid_request_types:
|
||||||
logger.debug("HTTP request made but unsupported request type given.")
|
logger.debug("HTTP request made but unsupported request type given.")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -115,7 +126,7 @@ class HTTPHandler(object):
|
|||||||
return responses[0]
|
return responses[0]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.debug("HTTP request made but no enpoint given.")
|
logger.debug("HTTP request made but no uri endpoint provided.")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _http_requests_pool(self, urls, workers=10, chunk=None):
|
def _http_requests_pool(self, urls, workers=10, chunk=None):
|
||||||
@@ -128,20 +139,13 @@ class HTTPHandler(object):
|
|||||||
if len(urls) == 0:
|
if len(urls) == 0:
|
||||||
chunk = 0
|
chunk = 0
|
||||||
|
|
||||||
if self.ssl_verify:
|
|
||||||
session = urllib3.PoolManager(cert_reqs=2, ca_certs=certifi.where()) # ssl.CERT_REQUIRED = 2
|
|
||||||
else:
|
|
||||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
|
||||||
session = urllib3.PoolManager()
|
|
||||||
part = partial(self._http_requests_urllib3, session=session)
|
|
||||||
|
|
||||||
if len(urls) == 1:
|
if len(urls) == 1:
|
||||||
yield part(urls[0])
|
yield self._http_requests_single(urls[0])
|
||||||
else:
|
else:
|
||||||
pool = ThreadPool(workers)
|
pool = ThreadPool(workers)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for work in pool.imap_unordered(part, urls, chunk):
|
for work in pool.imap_unordered(self._http_requests_single, urls, chunk):
|
||||||
yield work
|
yield work
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if not self._silent:
|
if not self._silent:
|
||||||
@@ -150,34 +154,40 @@ class HTTPHandler(object):
|
|||||||
pool.close()
|
pool.close()
|
||||||
pool.join()
|
pool.join()
|
||||||
|
|
||||||
def _http_requests_urllib3(self, url, session):
|
def _http_requests_single(self, url):
|
||||||
"""Request the data from the url"""
|
"""Request the data from the url"""
|
||||||
|
error_msg = "Failed to access uri endpoint %s. " % self.uri
|
||||||
try:
|
try:
|
||||||
r = session.request(self.request_type, url, headers=self.headers, fields=self.data,
|
r = self._session.request(self.request_type, url, headers=self.headers, data=self.data,
|
||||||
timeout=self.timeout, **self.request_kwargs)
|
timeout=self.timeout, verify=self.ssl_verify, **self.request_kwargs)
|
||||||
except IOError as e:
|
r.raise_for_status()
|
||||||
|
except requests.exceptions.Timeout as e:
|
||||||
if not self._silent:
|
if not self._silent:
|
||||||
logger.warn("Failed to access uri endpoint %s with error %s" % (self.uri, e))
|
logger.error(error_msg + "Request timed out: %s", e)
|
||||||
return None
|
return None
|
||||||
except Exception as e:
|
except requests.exceptions.SSLError as e:
|
||||||
if not self._silent:
|
if not self._silent:
|
||||||
logger.warn("Failed to access uri endpoint %s. Is your server maybe accepting SSL connections only? %s" % (self.uri, e))
|
logger.error(error_msg + "Is your server maybe accepting SSL connections only? %s", e)
|
||||||
return None
|
return None
|
||||||
except:
|
except requests.exceptions.HTTPError as e:
|
||||||
if not self._silent:
|
if not self._silent:
|
||||||
logger.warn("Failed to access uri endpoint %s with Uncaught exception." % self.uri)
|
logger.error(error_msg + "Status code %s", e)
|
||||||
|
return None
|
||||||
|
except requests.exceptions.ConnectionError as e:
|
||||||
|
if not self._silent:
|
||||||
|
logger.error(error_msg + "Connection error: %s", e)
|
||||||
|
return None
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
if not self._silent:
|
||||||
|
logger.error(error_msg + "Uncaught exception: %s", e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
response_status = r.status
|
response_status = r.status_code
|
||||||
response_content = r.data
|
response_content = r.content
|
||||||
response_headers = r.headers
|
response_headers = r.headers
|
||||||
|
|
||||||
if response_status in (200, 201):
|
if response_status in (200, 201):
|
||||||
return self._http_format_output(response_content, response_headers)
|
return self._http_format_output(response_content, response_headers)
|
||||||
else:
|
|
||||||
if not self._silent:
|
|
||||||
logger.warn("Failed to access uri endpoint %s. Status code %r" % (self.uri, response_status))
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _http_format_output(self, response_content, response_headers):
|
def _http_format_output(self, response_content, response_headers):
|
||||||
"""Formats the request response to the desired type"""
|
"""Formats the request response to the desired type"""
|
||||||
|
|||||||
Reference in New Issue
Block a user