async def test_aiter_raw(): stream = AsyncIteratorStream(aiterator=async_streaming_body()) response = httpx.Response(200, stream=stream, request=REQUEST) raw = b"" async for part in response.aiter_raw(): raw += part assert raw == b"Hello, world!"
async def test_text_decoder(data, encoding): async def iterator(): nonlocal data for chunk in data: yield chunk # Accessing `.text` on a read response. stream = AsyncIteratorStream(aiterator=iterator()) response = httpx.Response(200, stream=stream, request=REQUEST) await response.aread() assert response.text == (b"".join(data)).decode(encoding) # Streaming `.aiter_text` iteratively. stream = AsyncIteratorStream(aiterator=iterator()) response = httpx.Response(200, stream=stream, request=REQUEST) text = "".join([part async for part in response.aiter_text()]) assert text == (b"".join(data)).decode(encoding)
async def test_cannot_read_after_response_closed(): stream = AsyncIteratorStream(aiterator=async_streaming_body()) response = httpx.Response(200, stream=stream, request=REQUEST) await response.aclose() with pytest.raises(httpx.ResponseClosed): await response.aread()
async def test_cannot_read_after_stream_consumed(): stream = AsyncIteratorStream(aiterator=async_streaming_body()) response = httpx.Response(200, stream=stream, request=REQUEST) content = b"" async for part in response.aiter_bytes(): content += part with pytest.raises(httpx.StreamConsumed): await response.aread()
async def test_text_decoder(data, encoding): async def iterator(): nonlocal data for chunk in data: yield chunk stream = AsyncIteratorStream(aiterator=iterator()) response = httpx.Response(200, stream=stream, request=REQUEST) await response.aread() assert response.text == (b"".join(data)).decode(encoding)
async def test_streaming_response(): stream = AsyncIteratorStream(aiterator=async_streaming_body()) response = httpx.Response(200, stream=stream, request=REQUEST) assert response.status_code == 200 assert not response.is_closed content = await response.aread() assert content == b"Hello, world!" assert response.content == b"Hello, world!" assert response.is_closed
async def test_streaming(): body = b"test 123" compressor = zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS | 16) async def compress(body): yield compressor.compress(body) yield compressor.flush() headers = [(b"Content-Encoding", b"gzip")] stream = AsyncIteratorStream(aiterator=compress(body)) response = httpx.Response(200, headers=headers, stream=stream) assert not hasattr(response, "body") assert await response.read() == body
async def test_text_decoder_known_encoding(): async def iterator(): yield b"\x83g" yield b"\x83" yield b"\x89\x83x\x83\x8b" stream = AsyncIteratorStream(aiterator=iterator()) response = httpx.Response( 200, headers=[(b"Content-Type", b"text/html; charset=shift-jis")], stream=stream, ) await response.read() assert "".join(response.text) == "トラベル"
async def test_cannot_aread_after_response_closed(): is_closed = False async def close_func(): nonlocal is_closed is_closed = True stream = AsyncIteratorStream(aiterator=async_streaming_body(), close_func=close_func) response = httpx.Response(200, stream=stream, request=REQUEST) await response.aclose() assert is_closed with pytest.raises(httpx.ResponseClosed): await response.aread()
async def test_elapsed_not_available_until_closed(): stream = AsyncIteratorStream(aiterator=async_streaming_body()) response = httpx.Response(200, stream=stream, request=REQUEST) with pytest.raises(RuntimeError): response.elapsed
async def send( self, request: Request, verify: VerifyTypes = None, cert: CertTypes = None, timeout: TimeoutTypes = None, ) -> Response: if request.url.path == "/no_redirect": return Response(codes.OK, request=request) elif request.url.path == "/redirect_301": async def body(): yield b"<a href='https://example.org/'>here</a>" status_code = codes.MOVED_PERMANENTLY headers = {"location": "https://example.org/"} stream = AsyncIteratorStream(aiterator=body()) return Response(status_code, stream=stream, headers=headers, request=request) elif request.url.path == "/redirect_302": status_code = codes.FOUND headers = {"location": "https://example.org/"} return Response(status_code, headers=headers, request=request) elif request.url.path == "/redirect_303": status_code = codes.SEE_OTHER headers = {"location": "https://example.org/"} return Response(status_code, headers=headers, request=request) elif request.url.path == "/relative_redirect": headers = {"location": "/"} return Response(codes.SEE_OTHER, headers=headers, request=request) elif request.url.path == "/malformed_redirect": headers = {"location": "https://:443/"} return Response(codes.SEE_OTHER, headers=headers, request=request) elif request.url.path == "/no_scheme_redirect": headers = {"location": "//example.org/"} return Response(codes.SEE_OTHER, headers=headers, request=request) elif request.url.path == "/multiple_redirects": params = parse_qs(request.url.query) count = int(params.get("count", "0")[0]) redirect_count = count - 1 code = codes.SEE_OTHER if count else codes.OK location = "/multiple_redirects" if redirect_count: location += "?count=" + str(redirect_count) headers = {"location": location} if count else {} return Response(code, headers=headers, request=request) if request.url.path == "/redirect_loop": headers = {"location": "/redirect_loop"} return Response(codes.SEE_OTHER, headers=headers, request=request) elif request.url.path == "/cross_domain": headers = {"location": "https://example.org/cross_domain_target"} return Response(codes.SEE_OTHER, headers=headers, request=request) elif request.url.path == "/cross_domain_target": headers = dict(request.headers.items()) content = json.dumps({"headers": headers}).encode() return Response(codes.OK, content=content, request=request) elif request.url.path == "/redirect_body": body = b"".join([part async for part in request.stream]) headers = {"location": "/redirect_body_target"} return Response(codes.PERMANENT_REDIRECT, headers=headers, request=request) elif request.url.path == "/redirect_no_body": content = b"".join([part async for part in request.stream]) headers = {"location": "/redirect_body_target"} return Response(codes.SEE_OTHER, headers=headers, request=request) elif request.url.path == "/redirect_body_target": content = b"".join([part async for part in request.stream]) headers = dict(request.headers.items()) body = json.dumps({ "body": content.decode(), "headers": headers }).encode() return Response(codes.OK, content=body, request=request) elif request.url.path == "/cross_subdomain": if request.headers["host"] != "www.example.org": headers = { "location": "https://www.example.org/cross_subdomain" } return Response(codes.PERMANENT_REDIRECT, headers=headers, request=request) else: return Response(codes.OK, content=b"Hello, world!", request=request) return Response(codes.OK, content=b"Hello, world!", request=request)