Repository URL to install this package:
|
Version:
0.4.190 ▾
|
lib-py-b2b
/
request.py
|
|---|
import base64
import hashlib
import hmac
import json
from datetime import datetime
from dateutil.parser import isoparse
from lib_b2b.base import BaseClass
from lib_b2b.persistent import Persistable
from lib_b2b.util import UtilityEncoder
class Request(BaseClass, Persistable):
def __init__(self, headers, method, body, request_time: datetime,
query_params=None, uri_params=None,
context=None, stage_vars=None,
request_type: 'OrderRequestType' = None,
is_base64_encoded: bool = False):
self.is_base64_encoded = is_base64_encoded
self.request_type = request_type
self.request_time = request_time
self.query_params = query_params
self.headers = headers
self.uri_params = uri_params
self.method = method
self.body = body
self._json_body = None
self._raw_body = b''
self.context = context
self.stage_vars = stage_vars
@property
def json_body(self):
if self.headers.get('content-type', '').startswith('application/json') or \
self.headers.get('Content-Type', '').startswith('application/json') or \
self.headers.get('CONTENT-TYPE', '').startswith('application/json'):
if self._json_body is None:
try:
self._json_body = json.loads(self.raw_body)
except ValueError as ve:
raise ValueError('Error Parsing JSON') from ve
return self._json_body
else:
raise ValueError('Invalid content-type')
@property
def raw_body(self):
if not self._raw_body and self.body is not None:
if self.is_base64_encoded:
self._raw_body = self._base64decode(self.body)
elif not isinstance(self.body, bytes):
self._raw_body = self.body.encode('utf-8')
else:
self._raw_body = self.body
return self._raw_body
def _base64decode(self, encoded):
if not isinstance(encoded, bytes):
encoded = encoded.encode('ascii')
output = base64.b64decode(encoded)
return output
def _base64encode(self, to_encode):
if not isinstance(to_encode, bytes):
to_encode = to_encode.encode('utf-8')
output = base64.b64encode(to_encode)
return output.decode('ascii')
@property
def statistics(self):
from boto3.dynamodb.types import TypeSerializer
ddb_serializer = TypeSerializer()
ddb_ser = ddb_serializer.serialize(self.as_dict())
ddb_ser_str = json.dumps(ddb_ser)
ddb_size = len(ddb_ser_str.encode('utf-8'))
json_size = len(json.dumps(self.as_dict()).encode('utf-8'))
encoded_json_size = len(json.dumps(self.as_dict(encoded=True)).encode('utf-8'))
signature = self.calculate_signature("thisisatestkeyforthepurposeoftesting".encode('utf-8'))
return {
'ddb_size': ddb_size,
'json_size': json_size,
'encoded_json_size': encoded_json_size,
'signature': signature
}
def calculate_signature(self, key: bytes):
_hash = hmac.new(key, self.raw_body, hashlib.sha256)
hmac_calculated = base64.b64encode(_hash.digest()).decode()
return hmac_calculated
@staticmethod
def from_(request, request_time: datetime, request_type: 'OrderRequestType' = None,
encoded: bool = False) -> 'Request':
return Request(
query_params=dict(request.query_params) if request.query_params else None,
headers=dict(request.headers) if request.headers else None,
uri_params=request.uri_params,
method=request.method,
body=request.raw_body.decode('utf-8'),
stage_vars=request.stage_vars,
context=request.context,
request_time=request_time,
request_type=request_type,
is_base64_encoded=encoded
)
@staticmethod
def from_dict(data: dict, encoded: bool = False):
from lib_b2b.order_request import OrderRequestType
if encoded:
encoded = data.get('body').encode('ascii')
body = base64.b64decode(encoded)
else:
body = data.get('body')
return Request(
query_params=data.get('query_params'),
headers=data.get('headers'),
uri_params=data.get('uri_params'),
method=data.get('method'),
body=body,
stage_vars=data.get('stage_vars'),
context=data.get('context'),
request_time=isoparse(data.get('request_time')),
request_type=OrderRequestType(data.get('request_type')) if data.get('request_type') else None,
is_base64_encoded=encoded
)
def as_dict(self, encoded: bool = False) -> dict:
_data = {
'query_params': self.query_params,
'headers': self.headers,
'uri_params': self.uri_params,
'method': self.method,
'body': self.body,
'stage_vars': self.stage_vars,
'context': self.context,
'request_time': self.request_time.isoformat(),
'request_type': self.request_type.value if self.request_type else None
}
if encoded:
_data['body'] = self._base64encode(self.raw_body)
return _data
def as_json(self):
return json.dumps(self.as_dict(), cls=UtilityEncoder)
@classmethod
def from_json(cls, json_str):
return cls.from_dict(json.loads(json_str))
def __eq__(self, other):
return self.headers == other.headers and self.body == other.body