class ResponseModelFactory(object): """given a response object, craft the silk response model""" def __init__(self, response): super(ResponseModelFactory, self).__init__() self.response = response self.request = DataCollector().request def body(self): body = '' content_type, char_set = _parse_content_type(self.response.get('Content-Type', '')) content = getattr(self.response, 'content', '') if char_set and content: try: content = content.decode(char_set) except AttributeError: pass except LookupError: # If no encoding exists, default to UTF-8 try: content = content.decode('UTF-8') except AttributeError: pass except UnicodeDecodeError: content = '' except Exception as e: Logger.error('Unable to decode response body using char_set %s due to error: %s. Will ignore. Stacktrace:' % (char_set, e)) traceback.print_exc() else: # Default to an attempt at UTF-8 decoding. try: content = content.decode('UTF-8') except AttributeError: pass except UnicodeDecodeError: content = '' if content: max_body_size = SilkyConfig().SILKY_MAX_RESPONSE_BODY_SIZE if max_body_size > -1: Logger.debug('Max size of response body defined so checking') size = sys.getsizeof(content, None) if not size: Logger.error('Could not get size of response body. Ignoring') content = '' else: if size > max_body_size: content = '' Logger.debug('Size of %d for %s is bigger than %d so ignoring response body' % (size, self.request.path, max_body_size)) else: Logger.debug('Size of %d for %s is less than %d so saving response body' % (size, self.request.path, max_body_size)) if content_type in content_types_json: # TODO: Perhaps theres a way to format the JSON without parsing it? try: body = json.dumps(json.loads(content), sort_keys=True, indent=4) except (TypeError, ValueError): Logger.warn('Response to request with pk %s has content type %s but was unable to parse it' % (self.request.pk, content_type)) return body, content def construct_response_model(self): assert self.request, 'Cant construct a response model if there is no request model' Logger.debug('Creating response model for request model with pk %s' % self.request.pk) b, content = self.body() raw_headers = self.response._headers headers = {} for k, v in raw_headers.items(): try: header, val = v except ValueError: header, val = k, v finally: headers[header] = val silky_response = models.Response.objects.create(request=self.request, status_code=self.response.status_code, encoded_headers=json.dumps(headers), body=b) # Text fields are encoded as UTF-8 in Django and hence will try to coerce # anything to we pass to UTF-8. Some stuff like binary will fail. try: silky_response.raw_body = content except UnicodeDecodeError: Logger.debug('NYI: Saving of binary response body') # TODO self.request.response = silky_response self.request.save() return silky_response