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'
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)
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
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)
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)]),
# 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)]),