Пример #1
0
def test_range() -> None:
    range_ = Range.from_header('bytes=500-600,601-999')
    assert range_.units == 'bytes'
    assert range_.ranges == [RangeSet(500, 600), RangeSet(601, 999)]
    assert range_.to_header() == 'bytes=500-600,601-999'
    range_ = Range.from_header('bytes=-999')
    assert range_.units == 'bytes'
    assert range_.ranges == [RangeSet(-999, None)]
    assert range_.to_header() == 'bytes=-999'
Пример #2
0
async def test_response_make_conditional() -> None:
    response = Response(b"abcdef")
    await response.make_conditional(Range("bytes", [RangeSet(0, 3)]))
    assert b"abc" == (await response.get_data())  # type: ignore
    assert response.status_code == 206
    assert response.accept_ranges == "bytes"
    assert response.content_range == ContentRange("bytes", 0, 2, 6)
Пример #3
0
def test_range(header: str, expected_ranges: List[RangeSet]) -> None:
    range_ = Range.from_header(header)
    assert range_.units == 'bytes'
    assert range_.ranges == expected_ranges
    assert range_.to_header() == header
Пример #4
0
def good_response(fileobj, headers=None, download=False):
    headers = headers or {}
    content_type = fileobj.content_type or 'application/octet-stream'
    if not isinstance(content_type, str):
        content_type = content_type.decode('utf8')

    headers['Content-Type'] = content_type
    modified = fileobj.modified or fileobj.created
    headers['Last-Modified'] = modified.strftime("%a, %d %b %Y %H:%M:%S GMT")
    headers['x-amz-version-id'] = str(fileobj.rev)
    for key, value in fileobj.meta.items():
        if isinstance(value, bytes):
            value = value.decode('utf8')
        else:
            value = str(value)
        headers['x-amz-meta-%s' % key] = value
    if download:
        headers[
            'Content-Disposition'] = 'attachment; filename="%s"' % os.path.basename(
                fileobj.path)

    status = 200
    headers['Accept-Ranges'] = 'bytes'
    brange = request.headers.get('range')

    body = b''
    to_read = -1
    ranger = None
    if not brange:
        etag = fileobj.meta.get('md5') or fileobj.meta.get('sha256') or ''
        if etag:
            headers['Etag'] = etag
        if etag and request.headers.get('if-none-match') == etag:
            status = 304
            body = b''
            to_read = 0
        else:
            if_date = request.headers.get('If-Modified-Since', '')
            if if_date:
                ts = datetime.strptime(if_date, "%a, %d %b %Y %H:%M:%S %Z")
                if ts >= modified:
                    status = 304
                    body = b''
                    to_read = 0
    else:
        try:
            ranger = Range.from_header(brange)
        except ValueError:
            print('BAD RANGE HEADER', brange)
        else:
            fr = ranger.ranges[0]

            headers['Content-Range'] = ContentRange(
                ranger.units, fr.begin, fr.end, fileobj.length).to_header()
            fileobj.seek(fr.begin)

            to_read = (fr.end - fr.begin) + 1
            status = 206

    if request.method == 'HEAD':
        resp = Response('', headers=headers)
        resp.content_length = fileobj.length
        return resp

    if status >= 200 and (fileobj.length >= 65535 and
                          (to_read == -1 or to_read >= 65535)):
        if to_read == -1:
            to_read = fileobj.length

        async def iterator(to_read):
            blocksize = getattr(fileobj, 'bs', 8192)
            # blocksize = 16384
            with fileobj:
                while to_read > 0:
                    chunk = await asynread(fileobj, min(to_read, blocksize))
                    if chunk:
                        yield chunk
                        to_read -= len(chunk)
                    else:
                        break

        return Response(iterator(to_read),
                        status=status,
                        headers=headers,
                        content_type=content_type)
    else:
        if to_read:
            with fileobj:
                body = fileobj.read(to_read)
            # print(repr(body))
        return Response(body,
                        headers=headers,
                        status=status,
                        content_type=content_type)
Пример #5
0
    assert b"Body" == (await response.get_data())  # type: ignore


@pytest.mark.asyncio
async def test_response_make_conditional() -> None:
    response = Response(b"abcdef")
    await response.make_conditional(Range("bytes", [RangeSet(0, 3)]))
    assert b"abc" == (await response.get_data())  # type: ignore
    assert response.status_code == 206
    assert response.accept_ranges == "bytes"
    assert response.content_range == ContentRange("bytes", 0, 2, 6)


@pytest.mark.asyncio
@pytest.mark.parametrize(
    "range_", [Range("", {}), Range("bytes", [RangeSet(0, 6)])])
async def test_response_make_conditional_no_condition(range_: Range) -> None:
    response = Response(b"abcdef")
    await response.make_conditional(range_)
    assert b"abcdef" == (await response.get_data())  # type: ignore
    assert response.status_code == 200
    assert response.accept_ranges == "bytes"


@pytest.mark.asyncio
@pytest.mark.parametrize(
    "range_",
    [
        Range("seconds", [RangeSet(0, 3)]),
        Range("bytes", [RangeSet(0, 2), RangeSet(3, 5)]),
        Range("bytes", [RangeSet(0, 8)]),
Пример #6
0
    # Fetch again to ensure it isn't exhausted
    assert b'Body' == (await response.get_data())  # type: ignore


@pytest.mark.asyncio
async def test_response_make_conditional() -> None:
    response = Response(b"abcdef")
    await response.make_conditional(Range("bytes", [RangeSet(0, 3)]))
    assert b"abc" == (await response.get_data())  # type: ignore
    assert response.status_code == 206
    assert response.accept_ranges == "bytes"
    assert response.content_range == ContentRange("bytes", 0, 2, 6)


@pytest.mark.asyncio
@pytest.mark.parametrize("range_", [Range("", {}), Range("bytes", [RangeSet(0, 6)])])
async def test_response_make_conditional_no_condition(range_: Range) -> None:
    response = Response(b"abcdef")
    await response.make_conditional(range_)
    assert b"abcdef" == (await response.get_data())  # type: ignore
    assert response.status_code == 200
    assert response.accept_ranges == "bytes"


@pytest.mark.asyncio
@pytest.mark.parametrize(
    "range_",
    [
        Range("seconds", [RangeSet(0, 3)]),
        Range("bytes", [RangeSet(0, 2), RangeSet(3, 5)]),
        Range("bytes", [RangeSet(0, 8)]),