Better handling of HTTP exceptions, and loop through server list URLs. See #86
This commit is contained in:
parent
b0e1e58a0b
commit
3ee45cace8
117
speedtest_cli.py
117
speedtest_cli.py
|
@ -139,6 +139,13 @@ else:
|
||||||
del builtins
|
del builtins
|
||||||
|
|
||||||
|
|
||||||
|
class SpeedtestCliServerListError(Exception):
|
||||||
|
"""Internal Exception class used to indicate to move on to the next
|
||||||
|
URL for retrieving speedtest.net server details
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def bound_socket(*args, **kwargs):
|
def bound_socket(*args, **kwargs):
|
||||||
"""Bind socket to a specified source IP address"""
|
"""Bind socket to a specified source IP address"""
|
||||||
|
|
||||||
|
@ -177,6 +184,19 @@ def build_request(url, data=None, headers={}):
|
||||||
return Request(url, data=data, headers=headers)
|
return Request(url, data=data, headers=headers)
|
||||||
|
|
||||||
|
|
||||||
|
def catch_request(request):
|
||||||
|
"""Helper function to catch common exceptions encountered when
|
||||||
|
establishing a connection with a HTTP/HTTPS request
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
uh = urlopen(request)
|
||||||
|
return uh
|
||||||
|
except (HTTPError, URLError, socket.error):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class FileGetter(threading.Thread):
|
class FileGetter(threading.Thread):
|
||||||
"""Thread class for retrieving a URL"""
|
"""Thread class for retrieving a URL"""
|
||||||
|
|
||||||
|
@ -320,7 +340,10 @@ def getConfig():
|
||||||
"""
|
"""
|
||||||
|
|
||||||
request = build_request('http://www.speedtest.net/speedtest-config.php')
|
request = build_request('http://www.speedtest.net/speedtest-config.php')
|
||||||
uh = urlopen(request)
|
uh = catch_request(request)
|
||||||
|
if uh is False:
|
||||||
|
print_('Could not retrieve speedtest.net configuration')
|
||||||
|
sys.exit(1)
|
||||||
configxml = []
|
configxml = []
|
||||||
while 1:
|
while 1:
|
||||||
configxml.append(uh.read(10240))
|
configxml.append(uh.read(10240))
|
||||||
|
@ -337,7 +360,7 @@ def getConfig():
|
||||||
'times': root.find('times').attrib,
|
'times': root.find('times').attrib,
|
||||||
'download': root.find('download').attrib,
|
'download': root.find('download').attrib,
|
||||||
'upload': root.find('upload').attrib}
|
'upload': root.find('upload').attrib}
|
||||||
except AttributeError:
|
except AttributeError: # Python3 branch
|
||||||
root = DOM.parseString(''.join(configxml))
|
root = DOM.parseString(''.join(configxml))
|
||||||
config = {
|
config = {
|
||||||
'client': getAttributesByTagName(root, 'client'),
|
'client': getAttributesByTagName(root, 'client'),
|
||||||
|
@ -357,43 +380,58 @@ def closestServers(client, all=False):
|
||||||
distance
|
distance
|
||||||
"""
|
"""
|
||||||
|
|
||||||
url = 'http://www.speedtest.net/speedtest-servers-static.php'
|
urls = [
|
||||||
request = build_request(url)
|
'http://c.speedtest.net/speedtest-servers-static.php',
|
||||||
uh = urlopen(request)
|
'http://www.speedtest.net/speedtest-servers-static.php',
|
||||||
serversxml = []
|
]
|
||||||
while 1:
|
|
||||||
serversxml.append(uh.read(10240))
|
|
||||||
if len(serversxml[-1]) == 0:
|
|
||||||
break
|
|
||||||
if int(uh.code) != 200:
|
|
||||||
return None
|
|
||||||
uh.close()
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
root = ET.fromstring(''.encode().join(serversxml))
|
|
||||||
elements = root.getiterator('server')
|
|
||||||
except AttributeError:
|
|
||||||
root = DOM.parseString(''.join(serversxml))
|
|
||||||
elements = root.getElementsByTagName('server')
|
|
||||||
except SyntaxError:
|
|
||||||
print_('Failed to parse list of speedtest.net servers')
|
|
||||||
sys.exit(1)
|
|
||||||
servers = {}
|
servers = {}
|
||||||
for server in elements:
|
for url in urls:
|
||||||
try:
|
try:
|
||||||
attrib = server.attrib
|
request = build_request(url)
|
||||||
except AttributeError:
|
uh = catch_request(request)
|
||||||
attrib = dict(list(server.attributes.items()))
|
if uh is False:
|
||||||
d = distance([float(client['lat']), float(client['lon'])],
|
raise SpeedtestCliServerListError
|
||||||
[float(attrib.get('lat')), float(attrib.get('lon'))])
|
serversxml = []
|
||||||
attrib['d'] = d
|
while 1:
|
||||||
if d not in servers:
|
serversxml.append(uh.read(10240))
|
||||||
servers[d] = [attrib]
|
if len(serversxml[-1]) == 0:
|
||||||
else:
|
break
|
||||||
servers[d].append(attrib)
|
if int(uh.code) != 200:
|
||||||
del root
|
uh.close()
|
||||||
del serversxml
|
raise SpeedtestCliServerListError
|
||||||
del elements
|
uh.close()
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
root = ET.fromstring(''.encode().join(serversxml))
|
||||||
|
elements = root.getiterator('server')
|
||||||
|
except AttributeError: # Python3 branch
|
||||||
|
root = DOM.parseString(''.join(serversxml))
|
||||||
|
elements = root.getElementsByTagName('server')
|
||||||
|
except SyntaxError:
|
||||||
|
raise SpeedtestCliServerListError
|
||||||
|
for server in elements:
|
||||||
|
try:
|
||||||
|
attrib = server.attrib
|
||||||
|
except AttributeError:
|
||||||
|
attrib = dict(list(server.attributes.items()))
|
||||||
|
d = distance([float(client['lat']),
|
||||||
|
float(client['lon'])],
|
||||||
|
[float(attrib.get('lat')),
|
||||||
|
float(attrib.get('lon'))])
|
||||||
|
attrib['d'] = d
|
||||||
|
if d not in servers:
|
||||||
|
servers[d] = [attrib]
|
||||||
|
else:
|
||||||
|
servers[d].append(attrib)
|
||||||
|
del root
|
||||||
|
del serversxml
|
||||||
|
del elements
|
||||||
|
except SpeedtestCliServerListError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not servers:
|
||||||
|
print_('Failed to retrieve list of speedtest.net servers')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
closest = []
|
closest = []
|
||||||
for d in sorted(servers.keys()):
|
for d in sorted(servers.keys()):
|
||||||
|
@ -688,7 +726,10 @@ def speedtest():
|
||||||
request = build_request('http://www.speedtest.net/api/api.php',
|
request = build_request('http://www.speedtest.net/api/api.php',
|
||||||
data='&'.join(apiData).encode(),
|
data='&'.join(apiData).encode(),
|
||||||
headers=headers)
|
headers=headers)
|
||||||
f = urlopen(request)
|
f = catch_request(request)
|
||||||
|
if f is False:
|
||||||
|
print_('Could not submit results to speedtest.net')
|
||||||
|
sys.exit(1)
|
||||||
response = f.read()
|
response = f.read()
|
||||||
code = f.code
|
code = f.code
|
||||||
f.close()
|
f.close()
|
||||||
|
|
Loading…
Reference in New Issue