From 2880673e27e41126416d8c642fb6851880eaa8e2 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Mon, 29 Jun 2020 13:01:40 +0300 Subject: [PATCH] drf_msgpack: add code to parse/serialise msgpack It's not actually used by clients but it's there and can be used. It works for receiving msgpack messages, but doesn't yet work for sending because some of the types will be converted to base64. --- django_etebase/drf_msgpack/__init__.py | 0 django_etebase/drf_msgpack/apps.py | 5 +++++ django_etebase/drf_msgpack/migrations/__init__.py | 0 django_etebase/drf_msgpack/parsers.py | 14 ++++++++++++++ django_etebase/drf_msgpack/renderers.py | 15 +++++++++++++++ django_etebase/drf_msgpack/views.py | 3 +++ django_etebase/views.py | 15 +++++++++++++-- 7 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 django_etebase/drf_msgpack/__init__.py create mode 100644 django_etebase/drf_msgpack/apps.py create mode 100644 django_etebase/drf_msgpack/migrations/__init__.py create mode 100644 django_etebase/drf_msgpack/parsers.py create mode 100644 django_etebase/drf_msgpack/renderers.py create mode 100644 django_etebase/drf_msgpack/views.py diff --git a/django_etebase/drf_msgpack/__init__.py b/django_etebase/drf_msgpack/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django_etebase/drf_msgpack/apps.py b/django_etebase/drf_msgpack/apps.py new file mode 100644 index 0000000..619e3e0 --- /dev/null +++ b/django_etebase/drf_msgpack/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class DrfMsgpackConfig(AppConfig): + name = 'drf_msgpack' diff --git a/django_etebase/drf_msgpack/migrations/__init__.py b/django_etebase/drf_msgpack/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/django_etebase/drf_msgpack/parsers.py b/django_etebase/drf_msgpack/parsers.py new file mode 100644 index 0000000..44cd33b --- /dev/null +++ b/django_etebase/drf_msgpack/parsers.py @@ -0,0 +1,14 @@ +import msgpack + +from rest_framework.parsers import BaseParser +from rest_framework.exceptions import ParseError + + +class MessagePackParser(BaseParser): + media_type = 'application/msgpack' + + def parse(self, stream, media_type=None, parser_context=None): + try: + return msgpack.unpackb(stream.read(), raw=False) + except Exception as exc: + raise ParseError('MessagePack parse error - %s' % str(exc)) diff --git a/django_etebase/drf_msgpack/renderers.py b/django_etebase/drf_msgpack/renderers.py new file mode 100644 index 0000000..9445231 --- /dev/null +++ b/django_etebase/drf_msgpack/renderers.py @@ -0,0 +1,15 @@ +import msgpack + +from rest_framework.renderers import BaseRenderer + + +class MessagePackRenderer(BaseRenderer): + media_type = 'application/msgpack' + format = 'msgpack' + render_style = 'binary' + charset = None + + def render(self, data, media_type=None, renderer_context=None): + if data is None: + return b'' + return msgpack.packb(data, use_bin_type=True) diff --git a/django_etebase/drf_msgpack/views.py b/django_etebase/drf_msgpack/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/django_etebase/drf_msgpack/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/django_etebase/views.py b/django_etebase/views.py index c7fdab5..93a7645 100644 --- a/django_etebase/views.py +++ b/django_etebase/views.py @@ -26,9 +26,10 @@ from django.shortcuts import get_object_or_404 from rest_framework import status from rest_framework import viewsets -from rest_framework import parsers from rest_framework.decorators import action as action_decorator from rest_framework.response import Response +from rest_framework.parsers import JSONParser, FormParser, MultiPartParser +from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer import nacl.encoding import nacl.signing @@ -37,6 +38,9 @@ import nacl.hash from .token_auth.models import AuthToken +from .drf_msgpack.parsers import MessagePackParser +from .drf_msgpack.renderers import MessagePackRenderer + from . import app_settings, permissions from .models import ( Collection, @@ -83,6 +87,8 @@ def msgpack_decode(content): class BaseViewSet(viewsets.ModelViewSet): authentication_classes = tuple(app_settings.API_AUTHENTICATORS) permission_classes = tuple(app_settings.API_PERMISSIONS) + renderer_classes = [JSONRenderer, MessagePackRenderer, BrowsableAPIRenderer] + parser_classes = [JSONParser, MessagePackParser, FormParser, MultiPartParser] stoken_id_fields = None def get_serializer_class(self): @@ -398,9 +404,10 @@ class CollectionItemViewSet(BaseViewSet): class CollectionItemChunkViewSet(viewsets.ViewSet): allowed_methods = ['GET', 'POST'] - parser_classes = (parsers.MultiPartParser, ) authentication_classes = BaseViewSet.authentication_classes permission_classes = BaseViewSet.permission_classes + renderer_classes = BaseViewSet.renderer_classes + parser_classes = (MultiPartParser, ) serializer_class = CollectionItemChunkSerializer lookup_field = 'uid' @@ -602,6 +609,8 @@ class InvitationIncomingViewSet(InvitationBaseViewSet): class AuthenticationViewSet(viewsets.ViewSet): allowed_methods = ['POST'] authentication_classes = BaseViewSet.authentication_classes + renderer_classes = BaseViewSet.renderer_classes + parser_classes = BaseViewSet.parser_classes def get_encryption_key(self, salt): key = nacl.hash.blake2b(settings.SECRET_KEY.encode(), encoder=nacl.encoding.RawEncoder) @@ -757,6 +766,8 @@ class AuthenticationViewSet(viewsets.ViewSet): class TestAuthenticationViewSet(viewsets.ViewSet): allowed_methods = ['POST'] + renderer_classes = BaseViewSet.renderer_classes + parser_classes = BaseViewSet.parser_classes def list(self, request): return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)