Merge pull request #1385 from elpollodiablo/master

Change http_handler to use requests instead of urllib3
This commit is contained in:
JonnyWong16 2020-12-18 14:11:53 -08:00 committed by GitHub
commit 562c726787
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -19,11 +19,11 @@ from __future__ import unicode_literals
from future.builtins import object
from future.builtins import str
from functools import partial
from multiprocessing.dummy import Pool as ThreadPool
from future.moves.urllib.parse import urljoin
import certifi
import requests
import urllib3
import plexpy
@ -41,6 +41,7 @@ class HTTPHandler(object):
"""
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
if isinstance(urls, str):
@ -51,24 +52,34 @@ class HTTPHandler(object):
if headers:
self.headers = headers
else:
self.headers = {'X-Plex-Product': plexpy.common.PRODUCT,
'X-Plex-Version': plexpy.common.RELEASE,
'X-Plex-Client-Identifier': plexpy.CONFIG.PMS_UUID,
'X-Plex-Platform': plexpy.common.PLATFORM,
'X-Plex-Platform-Version': plexpy.common.PLATFORM_RELEASE,
'X-Plex-Device': '{} {}'.format(plexpy.common.PLATFORM,
plexpy.common.PLATFORM_RELEASE),
'X-Plex-Device-Name': plexpy.common.PLATFORM_DEVICE_NAME
}
self.headers = {
'X-Plex-Product': plexpy.common.PRODUCT,
'X-Plex-Version': plexpy.common.RELEASE,
'X-Plex-Client-Identifier': plexpy.CONFIG.PMS_UUID,
'X-Plex-Platform': plexpy.common.PLATFORM,
'X-Plex-Platform-Version': plexpy.common.PLATFORM_RELEASE,
'X-Plex-Device': '{} {}'.format(plexpy.common.PLATFORM,
plexpy.common.PLATFORM_RELEASE),
'X-Plex-Device-Name': plexpy.common.PLATFORM_DEVICE_NAME
}
self.token = token
if self.token:
self.headers['X-Plex-Token'] = self.token
self._session = requests.Session()
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,
uri=None,
@ -96,7 +107,7 @@ class HTTPHandler(object):
self.timeout = timeout or self.timeout
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.")
return None
@ -115,7 +126,7 @@ class HTTPHandler(object):
return responses[0]
else:
logger.debug("HTTP request made but no enpoint given.")
logger.debug("HTTP request made but no uri endpoint provided.")
return None
def _http_requests_pool(self, urls, workers=10, chunk=None):
@ -128,20 +139,13 @@ class HTTPHandler(object):
if len(urls) == 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:
yield part(urls[0])
yield self._http_requests_single(urls[0])
else:
pool = ThreadPool(workers)
try:
for work in pool.imap_unordered(part, urls, chunk):
for work in pool.imap_unordered(self._http_requests_single, urls, chunk):
yield work
except Exception as e:
if not self._silent:
@ -150,34 +154,40 @@ class HTTPHandler(object):
pool.close()
pool.join()
def _http_requests_urllib3(self, url, session):
def _http_requests_single(self, url):
"""Request the data from the url"""
error_msg = "Failed to access uri endpoint %s. " % self.uri
try:
r = session.request(self.request_type, url, headers=self.headers, fields=self.data,
timeout=self.timeout, **self.request_kwargs)
except IOError as e:
r = self._session.request(self.request_type, url, headers=self.headers, data=self.data,
timeout=self.timeout, verify=self.ssl_verify, **self.request_kwargs)
r.raise_for_status()
except requests.exceptions.Timeout as e:
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
except Exception as e:
except requests.exceptions.SSLError as e:
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
except:
except requests.exceptions.HTTPError as e:
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
response_status = r.status
response_content = r.data
response_status = r.status_code
response_content = r.content
response_headers = r.headers
if response_status in (200, 201):
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):
"""Formats the request response to the desired type"""