From 8993d7e0bb7c7b0f263fcbbca92cf6430afdedba Mon Sep 17 00:00:00 2001 From: Marco Marche Date: Tue, 19 Jan 2016 10:03:47 +0100 Subject: [PATCH 1/2] Response bodies are now stored b64 encoded (support for binary responses). This closes #85, closes #1 --- silk/model_factory.py | 32 +++----------------------------- silk/models.py | 5 +++++ silk/templates/silk/request.html | 16 +++++++++------- silk/views/raw.py | 7 +++++-- 4 files changed, 22 insertions(+), 38 deletions(-) diff --git a/silk/model_factory.py b/silk/model_factory.py index adc86405..594b2be6 100644 --- a/silk/model_factory.py +++ b/silk/model_factory.py @@ -2,6 +2,7 @@ import logging import sys import traceback +import base64 from uuid import UUID from django.core.urlresolvers import resolve @@ -197,29 +198,6 @@ 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: @@ -259,10 +237,6 @@ def construct_response_model(self): 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 + silky_response.raw_body = base64.b64encode(content) + return silky_response diff --git a/silk/models.py b/silk/models.py index 9cb257a0..45254122 100644 --- a/silk/models.py +++ b/silk/models.py @@ -1,5 +1,6 @@ from collections import Counter import json +import base64 from django.db import models from django.db.models import DateTimeField, TextField, CharField, ForeignKey, IntegerField, BooleanField, F, \ @@ -126,6 +127,10 @@ def headers(self): raw = {} return CaseInsensitiveDictionary(raw) + @property + def raw_body_decoded(self): + return base64.b64decode(self.raw_body) + # TODO rewrite docstring class SQLQueryManager(models.Manager): diff --git a/silk/templates/silk/request.html b/silk/templates/silk/request.html index 864932f6..8556964b 100644 --- a/silk/templates/silk/request.html +++ b/silk/templates/silk/request.html @@ -152,13 +152,15 @@ {% endif %} {% if silk_request.response.raw_body %} {% heading 'Raw Response Body' %} - {% if silk_request.response.raw_body|length > 1000 %} - The raw response body is {{ silk_request.response.raw_body|length }} characters long - and hence is too big to show here. - Click here to view the raw response body. - {% else %} -
{{ silk_request.response.raw_body }}
- {% endif %} + {% with raw_body=silk_request.response.raw_body_decoded %} + {% if raw_body|length > 1000 %} + The raw response body is {{ raw_body|length }} characters long + and hence is too big to show here. + Click here to view the raw response body. + {% else %} +
{{ raw_body }}
+ {% endif %} + {% endwith %} {% endif %} {% if silk_request.response.body %} {% heading 'Response Body' %} diff --git a/silk/views/raw.py b/silk/views/raw.py index 8a636feb..ad9fb1e9 100644 --- a/silk/views/raw.py +++ b/silk/views/raw.py @@ -4,6 +4,8 @@ from django.views.generic import View from silk.auth import login_possibly_required, permissions_possibly_required from silk.models import Request +import logging +Logger = logging.getLogger('silk') class Raw(View): @@ -17,9 +19,10 @@ def get(self, request, request_id): if typ and subtyp: silk_request = Request.objects.get(pk=request_id) if typ == 'request': - body = silk_request.raw_body if subtyp == 'raw' else silk_request.body + body = silk_request.raw_body_ if subtyp == 'raw' else silk_request.body elif typ == 'response': - body = silk_request.response.raw_body if subtyp == 'raw' else silk_request.response.body + Logger.debug(silk_request.response.raw_body_decoded) + body = silk_request.response.raw_body_decoded if subtyp == 'raw' else silk_request.response.body return render_to_response('silk/raw.html', { 'body': body }) From a4ace2c092395855925b702e06acb23829c3f7b5 Mon Sep 17 00:00:00 2001 From: Marco Marche Date: Tue, 19 Jan 2016 10:05:19 +0100 Subject: [PATCH 2/2] typo --- silk/views/raw.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/silk/views/raw.py b/silk/views/raw.py index ad9fb1e9..c5ca4254 100644 --- a/silk/views/raw.py +++ b/silk/views/raw.py @@ -19,7 +19,7 @@ def get(self, request, request_id): if typ and subtyp: silk_request = Request.objects.get(pk=request_id) if typ == 'request': - body = silk_request.raw_body_ if subtyp == 'raw' else silk_request.body + body = silk_request.raw_body if subtyp == 'raw' else silk_request.body elif typ == 'response': Logger.debug(silk_request.response.raw_body_decoded) body = silk_request.response.raw_body_decoded if subtyp == 'raw' else silk_request.response.body