blob: e23de2ae88224eb72c7cc99593587ca0e8f7bbba [file] [log] [blame]
"""Whisk Utility methods.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"""
import os
import json
import sys
if sys.version_info.major >= 3:
from http.client import HTTPConnection, HTTPSConnection, IncompleteRead
from urllib.parse import urlparse
else:
from httplib import HTTPConnection, HTTPSConnection, IncompleteRead
from urlparse import urlparse
import ssl
import base64
import socket
# global configurations, can control whether to allow untrusted certificates
# on HTTPS connections
httpRequestProps = {'secure': True}
def request(method, urlString, body = '', headers = {}, auth = None, verbose = False, https_proxy = os.getenv('https_proxy', None), timeout = 60):
url = urlparse(urlString)
if url.scheme == 'http':
conn = HTTPConnection(url.netloc, timeout = timeout)
else:
if httpRequestProps['secure'] or not hasattr(ssl, '_create_unverified_context'):
conn = HTTPSConnection(url.netloc if https_proxy is None else https_proxy, timeout = timeout)
else:
conn = HTTPSConnection(url.netloc if https_proxy is None else https_proxy, context=ssl._create_unverified_context(), timeout = timeout)
if https_proxy:
conn.set_tunnel(url.netloc)
if auth is not None:
auth = base64.b64encode(auth.encode()).decode()
headers['Authorization'] = 'Basic %s' % auth
if verbose:
print('========')
print('REQUEST:')
print('%s %s' % (method, urlString))
print('Headers sent:')
print(getPrettyJson(headers))
if body != '':
print('Body sent:')
print(body)
try:
conn.request(method, urlString, body, headers)
res = conn.getresponse()
body = ''
try:
body = res.read()
except IncompleteRead as e:
body = e.partial
# patch the read to return just the body since the normal read
# can only be done once
res.read = lambda: body
if verbose:
print('--------')
print('RESPONSE:')
print('Got response with code %s' % res.status)
print('Body received:')
print(res.read())
print('========')
return res
except socket.timeout:
return ErrorResponse(status = 500, error = 'request timed out at %d seconds' % timeout)
except Exception as e:
return ErrorResponse(status = 500, error = str(e))
def getPrettyJson(obj):
return json.dumps(obj, sort_keys=True, indent=4, separators=(',', ': '))
# class to normalize responses for exceptions with no HTTP response for canonical error handling
class ErrorResponse:
def __init__(self, status, error):
self.status = status
self.error = error
def read(self):
return self.error