84 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			84 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Python
		
	
	
	
from __future__ import annotations
 | 
						|
 | 
						|
import typing as t
 | 
						|
import zlib
 | 
						|
 | 
						|
from ._json import _CompactJSON
 | 
						|
from .encoding import base64_decode
 | 
						|
from .encoding import base64_encode
 | 
						|
from .exc import BadPayload
 | 
						|
from .serializer import _PDataSerializer
 | 
						|
from .serializer import Serializer
 | 
						|
from .timed import TimedSerializer
 | 
						|
 | 
						|
 | 
						|
class URLSafeSerializerMixin(Serializer[str]):
 | 
						|
    """Mixed in with a regular serializer it will attempt to zlib
 | 
						|
    compress the string to make it shorter if necessary. It will also
 | 
						|
    base64 encode the string so that it can safely be placed in a URL.
 | 
						|
    """
 | 
						|
 | 
						|
    default_serializer: _PDataSerializer[str] = _CompactJSON
 | 
						|
 | 
						|
    def load_payload(
 | 
						|
        self,
 | 
						|
        payload: bytes,
 | 
						|
        *args: t.Any,
 | 
						|
        serializer: t.Any | None = None,
 | 
						|
        **kwargs: t.Any,
 | 
						|
    ) -> t.Any:
 | 
						|
        decompress = False
 | 
						|
 | 
						|
        if payload.startswith(b"."):
 | 
						|
            payload = payload[1:]
 | 
						|
            decompress = True
 | 
						|
 | 
						|
        try:
 | 
						|
            json = base64_decode(payload)
 | 
						|
        except Exception as e:
 | 
						|
            raise BadPayload(
 | 
						|
                "Could not base64 decode the payload because of an exception",
 | 
						|
                original_error=e,
 | 
						|
            ) from e
 | 
						|
 | 
						|
        if decompress:
 | 
						|
            try:
 | 
						|
                json = zlib.decompress(json)
 | 
						|
            except Exception as e:
 | 
						|
                raise BadPayload(
 | 
						|
                    "Could not zlib decompress the payload before decoding the payload",
 | 
						|
                    original_error=e,
 | 
						|
                ) from e
 | 
						|
 | 
						|
        return super().load_payload(json, *args, **kwargs)
 | 
						|
 | 
						|
    def dump_payload(self, obj: t.Any) -> bytes:
 | 
						|
        json = super().dump_payload(obj)
 | 
						|
        is_compressed = False
 | 
						|
        compressed = zlib.compress(json)
 | 
						|
 | 
						|
        if len(compressed) < (len(json) - 1):
 | 
						|
            json = compressed
 | 
						|
            is_compressed = True
 | 
						|
 | 
						|
        base64d = base64_encode(json)
 | 
						|
 | 
						|
        if is_compressed:
 | 
						|
            base64d = b"." + base64d
 | 
						|
 | 
						|
        return base64d
 | 
						|
 | 
						|
 | 
						|
class URLSafeSerializer(URLSafeSerializerMixin, Serializer[str]):
 | 
						|
    """Works like :class:`.Serializer` but dumps and loads into a URL
 | 
						|
    safe string consisting of the upper and lowercase character of the
 | 
						|
    alphabet as well as ``'_'``, ``'-'`` and ``'.'``.
 | 
						|
    """
 | 
						|
 | 
						|
 | 
						|
class URLSafeTimedSerializer(URLSafeSerializerMixin, TimedSerializer[str]):
 | 
						|
    """Works like :class:`.TimedSerializer` but dumps and loads into a
 | 
						|
    URL safe string consisting of the upper and lowercase character of
 | 
						|
    the alphabet as well as ``'_'``, ``'-'`` and ``'.'``.
 | 
						|
    """
 |