2018-07-13 02:46:02 +10:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from __future__ import absolute_import, division, unicode_literals
|
2020-12-19 03:10:20 +11:00
|
|
|
from future import standard_library
|
|
|
|
standard_library.install_aliases()
|
|
|
|
from builtins import str
|
|
|
|
from builtins import object
|
2017-12-21 19:28:06 +11:00
|
|
|
from logging import getLogger
|
2020-12-19 03:10:20 +11:00
|
|
|
import http.client
|
2016-01-15 22:12:52 +11:00
|
|
|
import traceback
|
|
|
|
import string
|
2016-04-03 01:46:23 +11:00
|
|
|
import errno
|
|
|
|
from socket import error as socket_error
|
2016-04-07 02:23:51 +10:00
|
|
|
|
2016-09-03 01:20:19 +10:00
|
|
|
###############################################################################
|
|
|
|
|
2018-06-22 03:24:37 +10:00
|
|
|
LOG = getLogger('PLEX.httppersist')
|
2016-09-03 01:20:19 +10:00
|
|
|
|
|
|
|
###############################################################################
|
2016-01-15 22:12:52 +11:00
|
|
|
|
2016-04-03 01:46:23 +11:00
|
|
|
|
2020-12-19 03:10:20 +11:00
|
|
|
class RequestMgr(object):
|
2016-01-15 22:12:52 +11:00
|
|
|
def __init__(self):
|
|
|
|
self.conns = {}
|
|
|
|
|
|
|
|
def getConnection(self, protocol, host, port):
|
2017-12-21 19:28:06 +11:00
|
|
|
conn = self.conns.get(protocol + host + str(port), False)
|
2016-01-15 22:12:52 +11:00
|
|
|
if not conn:
|
2016-04-03 01:46:23 +11:00
|
|
|
if protocol == "https":
|
2020-12-19 03:10:20 +11:00
|
|
|
conn = http.client.HTTPSConnection(host, port)
|
2016-01-15 22:12:52 +11:00
|
|
|
else:
|
2020-12-19 03:10:20 +11:00
|
|
|
conn = http.client.HTTPConnection(host, port)
|
2017-12-21 19:28:06 +11:00
|
|
|
self.conns[protocol + host + str(port)] = conn
|
2016-01-15 22:12:52 +11:00
|
|
|
return conn
|
2016-04-03 01:46:23 +11:00
|
|
|
|
2016-01-15 22:12:52 +11:00
|
|
|
def closeConnection(self, protocol, host, port):
|
2017-12-21 19:28:06 +11:00
|
|
|
conn = self.conns.get(protocol + host + str(port), False)
|
2016-01-15 22:12:52 +11:00
|
|
|
if conn:
|
|
|
|
conn.close()
|
2017-12-21 19:28:06 +11:00
|
|
|
self.conns.pop(protocol + host + str(port), None)
|
2016-04-03 01:46:23 +11:00
|
|
|
|
2016-01-15 22:12:52 +11:00
|
|
|
def dumpConnections(self):
|
2020-12-19 03:10:20 +11:00
|
|
|
for conn in list(self.conns.values()):
|
2016-01-15 22:12:52 +11:00
|
|
|
conn.close()
|
|
|
|
self.conns = {}
|
2016-04-03 01:46:23 +11:00
|
|
|
|
2016-01-15 22:12:52 +11:00
|
|
|
def post(self, host, port, path, body, header={}, protocol="http"):
|
|
|
|
conn = None
|
|
|
|
try:
|
|
|
|
conn = self.getConnection(protocol, host, port)
|
|
|
|
header['Connection'] = "keep-alive"
|
|
|
|
conn.request("POST", path, body, header)
|
|
|
|
data = conn.getresponse()
|
|
|
|
if int(data.status) >= 400:
|
2017-12-21 19:28:06 +11:00
|
|
|
LOG.error("HTTP response error: %s" % str(data.status))
|
2016-04-03 01:46:23 +11:00
|
|
|
# this should return false, but I'm hacking it since iOS
|
|
|
|
# returns 404 no matter what
|
2016-01-15 22:12:52 +11:00
|
|
|
return data.read() or True
|
2016-04-03 01:46:23 +11:00
|
|
|
else:
|
2016-01-15 22:12:52 +11:00
|
|
|
return data.read() or True
|
2016-04-03 01:46:23 +11:00
|
|
|
except socket_error as serr:
|
|
|
|
# Ignore remote close and connection refused (e.g. shutdown PKC)
|
|
|
|
if serr.errno in (errno.WSAECONNABORTED, errno.WSAECONNREFUSED):
|
|
|
|
pass
|
|
|
|
else:
|
2017-12-21 19:28:06 +11:00
|
|
|
LOG.error("Unable to connect to %s\nReason:" % host)
|
|
|
|
LOG.error(traceback.print_exc())
|
|
|
|
self.conns.pop(protocol + host + str(port), None)
|
2016-01-15 22:12:52 +11:00
|
|
|
if conn:
|
|
|
|
conn.close()
|
|
|
|
return False
|
2016-11-06 02:28:59 +11:00
|
|
|
except Exception as e:
|
2017-12-21 19:28:06 +11:00
|
|
|
LOG.error("Exception encountered: %s", e)
|
2016-11-06 02:28:59 +11:00
|
|
|
# Close connection just in case
|
|
|
|
try:
|
|
|
|
conn.close()
|
2019-02-03 06:22:06 +11:00
|
|
|
except Exception:
|
2016-11-06 02:28:59 +11:00
|
|
|
pass
|
|
|
|
return False
|
2016-04-03 01:46:23 +11:00
|
|
|
|
|
|
|
def getwithparams(self, host, port, path, params, header={},
|
|
|
|
protocol="http"):
|
2016-01-15 22:12:52 +11:00
|
|
|
newpath = path + '?'
|
|
|
|
pairs = []
|
|
|
|
for key in params:
|
2017-12-21 19:28:06 +11:00
|
|
|
pairs.append(str(key) + '=' + str(params[key]))
|
2016-01-15 22:12:52 +11:00
|
|
|
newpath += string.join(pairs, '&')
|
|
|
|
return self.get(host, port, newpath, header, protocol)
|
2016-04-03 01:46:23 +11:00
|
|
|
|
2016-01-15 22:12:52 +11:00
|
|
|
def get(self, host, port, path, header={}, protocol="http"):
|
|
|
|
try:
|
|
|
|
conn = self.getConnection(protocol, host, port)
|
|
|
|
header['Connection'] = "keep-alive"
|
|
|
|
conn.request("GET", path, headers=header)
|
|
|
|
data = conn.getresponse()
|
|
|
|
if int(data.status) >= 400:
|
2017-12-21 19:28:06 +11:00
|
|
|
LOG.error("HTTP response error: %s", str(data.status))
|
2016-01-15 22:12:52 +11:00
|
|
|
return False
|
2016-04-03 01:46:23 +11:00
|
|
|
else:
|
2016-01-15 22:12:52 +11:00
|
|
|
return data.read() or True
|
2016-04-05 18:57:30 +10:00
|
|
|
except socket_error as serr:
|
|
|
|
# Ignore remote close and connection refused (e.g. shutdown PKC)
|
|
|
|
if serr.errno in (errno.WSAECONNABORTED, errno.WSAECONNREFUSED):
|
|
|
|
pass
|
|
|
|
else:
|
2017-12-21 19:28:06 +11:00
|
|
|
LOG.error("Unable to connect to %s\nReason:", host)
|
|
|
|
LOG.error(traceback.print_exc())
|
|
|
|
self.conns.pop(protocol + host + str(port), None)
|
2016-01-15 22:12:52 +11:00
|
|
|
conn.close()
|
|
|
|
return False
|