Example #1
0
    def decode_cursor(self, request):
        """
        Given a request with a cursor, return a `Cursor` instance.

        Differs from the standard CursorPagination to handle a tuple in the
        position field.
        """
        # Determine if we have a cursor, and if so then decode it.
        encoded = request.query_params.get(self.cursor_query_param)
        if encoded is None:
            return None

        try:
            querystring = b64decode(encoded.encode('ascii')).decode('ascii')
            tokens = parse.parse_qs(querystring, keep_blank_values=True)

            offset = tokens.get('o', ['0'])[0]
            offset = _positive_int(offset, cutoff=self.offset_cutoff)

            reverse = tokens.get('r', ['0'])[0]
            reverse = bool(int(reverse))

            # The difference. Don't get just the 0th entry: get all entries.
            position = tokens.get('p', None)
        except (TypeError, ValueError):
            raise NotFound(self.invalid_cursor_message)

        return Cursor(offset=offset, reverse=reverse, position=position)
Example #2
0
    def decode_cursor(self, request):
        """
        Given a request with a cursor, return a `Cursor` instance.
        """
        # Determine if we have a cursor, and if so then decode it.
        encoded = request.query_params.get(self.cursor_query_param)
        if encoded is None:
            return None

        # The offset in the cursor is used in situations where we have a
        # nearly-unique index. (Eg millisecond precision creation timestamps)
        # We guard against malicious users attempting to cause expensive database
        # queries, by having a hard cap on the maximum possible size of the offset.
        OFFSET_CUTOFF = getattr(settings, 'CURSOR_PAGINATION_OFFSET_CUTOFF',
                                1000)

        try:
            querystring = b64decode(encoded.encode('ascii')).decode('ascii')
            tokens = parse_qs(querystring, keep_blank_values=True)

            offset = tokens.get('o', ['0'])[0]
            offset = _positive_int(offset, cutoff=OFFSET_CUTOFF)

            reverse = tokens.get('r', ['0'])[0]
            reverse = bool(int(reverse))

            position = tokens.get('p', [None])[0]
        except (TypeError, ValueError):
            raise NotFound(self.invalid_cursor_message)

        return Cursor(offset=offset, reverse=reverse, position=position)
Example #3
0
    def decode_cursor(self, request):
        """
        Given a request with a cursor, return a `Cursor` instance.
        """
        # Determine if we have a cursor, and if so then decode it.
        encoded = request.query_params.get(self.cursor_query_param)
        if encoded is None:
            return None

        try:
            reverse = False
            if encoded.startswith('-'):
                encoded = encoded[1:]
                reverse = True

            offset = 0
            parts = encoded.split('+', 1)
            if '-' in parts[0]:
                position = parts[0]
            else:
                position = None

            if len(parts) > 1:
                offset = _positive_int(parts[1], cutoff=self.offset_cutoff)

        except (TypeError, ValueError):
            raise NotFound(self.invalid_cursor_message)

        return Cursor(offset=offset, reverse=reverse, position=position)
Example #4
0
    def get_next_link(self):
        if not self.has_next:
            return None

        offset = self.page_size if not self.has_previous else self.cursor.offset + self.page_size

        cursor = Cursor(offset=offset, reverse=False, position=None)

        return self.encode_cursor(cursor)
Example #5
0
    def get_previous_link(self):
        if not self.has_previous:
            return None

        offset = self.cursor.offset - self.page_size
        if offset < 0:
            offset = 0

        cursor = Cursor(offset=offset, reverse=False, position=None)

        return self.encode_cursor(cursor)
Example #6
0
    def decode_cursor(self, request):
        bucket = self._context.get('bucket')
        key_marker = self.get_key_marker(request)
        position = None
        if key_marker:
            try:
                upload = MultipartUploadManager().get_multipart_upload_delete_invalid(bucket=bucket, obj_path=key_marker)
            except exceptions.S3Error as e:
                raise e

            if upload:
                position = upload.create_time
            else:
                upload_id_marker = self.get_upload_id_marker(request)
                if upload_id_marker:
                    position = get_datetime_from_upload_id(upload_id_marker)
                else:
                    raise exceptions.S3NoSuchUpload('key-marker upload not found.')

        return Cursor(offset=0, reverse=False, position=position)
Example #7
0
    def _get_start_after_cursor(self, start_after):
        """
        获取分页起始参数start_after对应的游标cursor

        :param start_after: 对象Key
        :return:
            Cursor() or None

        :raises: S3Error
        """
        hm = HarborManager()
        bucket = self._context.get('bucket', None)
        if not bucket:
            bucket_name = self._context('bucket_name')
            bucket = hm.get_bucket(bucket_name=bucket_name)

        if not bucket:
            return None

        table_name = bucket.get_bucket_table_name()
        try:
            obj = HarborManager().get_metadata_obj(table_name=table_name, path=start_after)
        except exceptions.S3Error as e:
            raise e

        if not obj:
            raise exceptions.S3NoSuchKey(_('无效的参数start_after'))

        order = self.ordering[0]
        is_reversed = order.startswith('-')
        attr = obj.id  # order by id
        if is_reversed:  # 倒序
            position = max(attr - 1, 0)
            reverse = False
        else:
            position = attr + 1
            reverse = True

        return Cursor(offset=0, reverse=reverse, position=position)
Example #8
0
 def decode_cursor(self, request):
     key_marker = self.get_key_marker(request)
     position = key_marker if key_marker else None
     return Cursor(offset=0, reverse=False, position=position)