hacking-jack's picture
Upload 1579 files
8070315 verified
Raw
History Blame Contribute Delete
3.97 kB
import hashlib, hmac, base64
from datetime import datetime, tzinfo, timedelta
import requests
import urllib
import json
class PandaRequest(object):
def __init__(self, verb, path, cred, data={}, timestamp=None):
self.verb = verb.upper()
self.path = self.canonical_path(path)
self.cred = cred
self.data = data
self.timestamp = timestamp
for name, val in self.data.iteritems():
if isinstance(val, dict):
self.data[name] = json.dumps(val)
signed_params = self.signed_params()
self.files = None
if self.verb == 'POST' and ('file' in data):
self.files = {'file': open(data['file'], 'rb')}
self.requests_url = '%s%s' % (self.api_url(), path + "?" + self.canonical_querystring(signed_params))
def send(self):
req = getattr(requests, self.verb.lower())(self.requests_url, files=self.files)
return req.text
def signed_params(self):
auth_params = self.data.copy()
auth_params['cloud_id'] = self.cred["cloud_id"]
auth_params['access_key'] = self.cred["access_key"]
auth_params['timestamp'] = self.timestamp or self.generate_timestamp()
additional_args = auth_params.copy()
additional_args.update(auth_params)
# NOTE: when creating the authorisation signature for this request do not include the file parameter.
if 'file' in additional_args:
del(additional_args['file'])
auth_params['signature'] = self.generate_signature(self.verb, self.path, self.cred["api_host"], self.cred["secret_key"], additional_args)
return auth_params
def api_protocol(self):
if str(self.cred["api_port"]) == '443':
return 'https'
else:
return 'http'
def api_url(self):
return self.api_protocol() + '://' + self.api_host_and_port() + self.api_path()
def api_host_and_port(self):
ret = self.cred["api_host"]
if str(self.cred["api_port"]) != '80':
ret += ':' + str(self.cred["api_port"])
return ret
def api_path(self):
return '/v' + str(self.cred["api_version"])
def generate_signature(self, verb, request_uri, host, secret_key, params={}):
query_string = self.canonical_querystring(params)
string_to_sign = (
verb.upper() + "\n" +
host.lower() + "\n" +
request_uri + "\n" +
query_string
)
signature = hmac.new(secret_key, string_to_sign, hashlib.sha256).digest()
return base64.b64encode(signature).strip()
def urlescape(self, s):
s = unicode(s).encode('utf-8')
return urllib.quote(s).replace("%7E", "~").replace(' ', '%20').replace('/', '%2F')
def canonical_path(self, path):
return '/' + path.strip(' \t\n\r\0\x0B/')
def canonical_querystring(self, d):
def recursion(d, base=None):
pairs = []
ordered_params = sorted([(k, v) for k, v in d.iteritems()])
for key, value in ordered_params:
if key == 'file':
continue
if hasattr(value, 'values'):
pairs += recursion(value, key)
else:
new_pair = None
if base:
new_pair = "%s[%s]=%s" % (base, self.urlescape(key), self.urlescape(value))
else:
new_pair = "%s=%s" % (self.urlescape(key), self.urlescape(value))
pairs.append(new_pair)
return pairs
return '&'.join(recursion(d))
def generate_timestamp(self):
return datetime.now(UTC()).isoformat()
class UTC(tzinfo):
"""UTC"""
def utcoffset(self, dt):
return timedelta(0)
def tzname(self, dt):
return "UTC"
def dst(self, dt):
return timedelta(0)