''' API client for bocal-site ''' import json import urllib.request import hmac import hashlib from datetime import datetime def sendReq(url): def send(payload, host): try: req = urllib.request.Request('http://{}/{}'.format(host, url), json.dumps(payload).encode('ascii')) req.add_header('Content-Type', 'application/json') handle = urllib.request.urlopen(req) code = handle.getcode() content = handle.read() handle.close() return (code, content.decode('utf-8')) except urllib.error.HTTPError as e: return (e.code, e.read().decode('utf-8')) def authentify(apiKey, payload): keyId, key = apiKey.split('$') keyId = int(keyId) time = datetime.now().timestamp() mac = hmac.new(key.encode('utf-8'), msg=str(int(time)).encode('utf-8'), digestmod=hashlib.sha256) mac.update(json.dumps(payload).encode('utf-8')) auth = { 'keyId': keyId, 'timestamp': time, 'hmac': mac.hexdigest(), } return { 'auth': auth, 'req': payload, } def decorator(fct): ''' Decorator. Adds authentication layer. ''' def wrap(host, apiKey, *args, **kwargs): innerReq = fct(*args, **kwargs) payload = authentify(apiKey, innerReq) return send(payload, host) return wrap return decorator @sendReq(url='api/publish') def publish(bocId, url, date): return { 'id': bocId, 'url': url, 'date': date.strftime('%Y-%m-%d'), }