# pylint: disable=protected-access, unexpected-keyword-arg, bad-option-value, redefined-variable-type, too-many-locals
"""
A high-level module for getting JSON information from web services.
The HTTP vs HTTPS and certificate handling is done here.
:author: Daniel Abercrombie <dabercro@mit.edu>
"""
import os
import time
import re
import stat
import json
import httplib
import ssl
import urllib
import subprocess
[docs]def get_json(host, request, params='', body='', headers=None,
port=None, retries=3, **kwargs):
"""
Function for getting JSON from a URL that handles the connection
and certificates with just a couple of bools.
:param str host: The name of the host to connect to
:param str request: The request to make to the host
:param dict params: The parameters to pass to the request
:param str body: The body to send in a POST request
:param dict headers: Headers to pass to request. If ``None``,
``{'Accept': 'application/json'}`` will be passed.
:param int port: The port to access, if a not default value
:param int retries: The number of times to try to get the JSON response before giving up
:param kwargs: Additional aruments that can be used to change
the connection behavior.
These are listed below:
- use_https (bool) - Uses HTTP connection by default
- use_cert (bool) - Does not pass a certificate by default
- cert_file (str) - Default is ``$X509_USER_PROXY``.
- use_post (bool) - Determines whether to use POST or GET.
- cookie_file (str) - Location of a Shibboleth cookie to pass in header
- cookie_pem (str) - Location of ``.pem`` file to generate cookie
- cookie_key (str) - Location of ``.rsa`` key to generate cookie
- cookie_time (float) - Time, in seconds, until generating a new cookie
:returns: The JSON from the query
:rtype: dict
"""
check_for_port = host.split(':')
if len(check_for_port) == 2:
host = check_for_port[0]
port = int(check_for_port[1])
use_cert = kwargs.get('use_cert', False)
use_https = kwargs.get('use_https', use_cert or bool(kwargs.get('cookie_file')))
if use_https:
use_port = port or 443
cert_file = kwargs.get('cert_file', os.getenv('X509_USER_PROXY')) \
if use_cert else None
# Python 2.7.something verifies HTTPS connections,
# but earlier version of Python do not
try:
conn = httplib.HTTPSConnection(
host, use_port, cert_file=cert_file, key_file=cert_file,
context=ssl._create_unverified_context())
except AttributeError:
conn = httplib.HTTPSConnection(
host, use_port, cert_file=cert_file, key_file=cert_file)
else:
use_port = port or 80
conn = httplib.HTTPConnection(host, use_port)
method = "POST" if kwargs.get('use_post', bool(body)) else "GET"
full_request = '%s?%s' % (request, urllib.urlencode(params)) if params else request
header = headers or {'Accept': 'application/json'}
if kwargs.get('cookie_file'):
sso_request_url = 'https://%s:%i%s' % (host, use_port, full_request)
header['Cookie'] = get_cookie_header(sso_request_url, kwargs['cookie_file'],
kwargs.get('cookie_pem'), kwargs.get('cookie_key'),
kwargs.get('cookie_time'))[host]
tries = 0
while tries <= retries:
conn.request(
method, full_request, json.dumps(body), header)
res = conn.getresponse()
if res.status == 200:
result = json.loads(res.read())
conn.close()
return result
print("STATUS", res.status, "REASON", res.reason)
tries += 1
conn.close()
return {}