def test_streaming_body_requests(app): @app.post("/", stream=True) async def handler(request): data = [part.decode("utf-8") async for part in request.stream] return json({ "request_id": str(request.id), "connection_id": id(request.conn_info), "data": data, }) data = ["hello", "world"] class Data(AsyncByteStream): def __init__(self, data): self.data = data async def __aiter__(self): for value in self.data: yield value.encode("utf-8") client = ReusableClient(app, port=1234) with client: _, response1 = client.post("/", data=Data(data)) _, response2 = client.post("/", data=Data(data)) assert response1.status == response2.status == 200 assert response1.json["data"] == response2.json["data"] == data assert response1.json["request_id"] != response2.json["request_id"] assert response1.json["connection_id"] == response2.json["connection_id"]
def test_keep_alive_connection_context(): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) client = ReusableClient(keep_alive_app_context, loop=loop, port=PORT) with client: headers = {"Connection": "keep-alive"} request1, _ = client.post("/ctx", headers=headers) loop.run_until_complete(aio_sleep(1)) request2, response = client.get("/ctx") assert response.text == "hello" assert id(request1.conn_info.ctx) == id(request2.conn_info.ctx) assert (request1.conn_info.ctx.foo == request2.conn_info.ctx.foo == "hello") assert request2.protocol.state["requests_count"] == 2
def test_no_body_requests(app): @app.get("/") async def handler(request): return json({ "request_id": str(request.id), "connection_id": id(request.conn_info), }) client = ReusableClient(app, port=1234) with client: _, response1 = client.get("/") _, response2 = client.get("/") assert response1.status == response2.status == 200 assert response1.json["request_id"] != response2.json["request_id"] assert response1.json["connection_id"] == response2.json["connection_id"]
def test_keep_alive_client_timeout(): """If the server keep-alive timeout is longer than the client keep-alive timeout, client will try to create a new connection here.""" loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) client = ReusableClient(keep_alive_app_client_timeout, loop=loop, port=PORT) with client: headers = {"Connection": "keep-alive"} request, response = client.get("/1", headers=headers, timeout=1) assert response.status == 200 assert response.text == "OK" assert request.protocol.state["requests_count"] == 1 loop.run_until_complete(aio_sleep(2)) request, response = client.get("/1", timeout=1) assert request.protocol.state["requests_count"] == 1
def test_json_body_requests(app): @app.post("/") async def handler(request): return json({ "request_id": str(request.id), "connection_id": id(request.conn_info), "foo": request.json.get("foo"), }) client = ReusableClient(app, port=1234) with client: _, response1 = client.post("/", json={"foo": True}) _, response2 = client.post("/", json={"foo": True}) assert response1.status == response2.status == 200 assert response1.json["foo"] is response2.json["foo"] is True assert response1.json["request_id"] != response2.json["request_id"] assert response1.json["connection_id"] == response2.json["connection_id"]
def test_keep_alive_timeout_reuse(): """If the server keep-alive timeout and client keep-alive timeout are both longer than the delay, the client _and_ server will successfully reuse the existing connection.""" loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) client = ReusableClient(keep_alive_timeout_app_reuse, loop=loop, port=PORT) with client: headers = {"Connection": "keep-alive"} request, response = client.get("/1", headers=headers) assert response.status == 200 assert response.text == "OK" assert request.protocol.state["requests_count"] == 1 loop.run_until_complete(aio_sleep(1)) request, response = client.get("/1") assert response.status == 200 assert response.text == "OK" assert request.protocol.state["requests_count"] == 2
def test_bad_headers(app): @app.get("/") async def handler(request): return text("") @app.on_response async def reqid(request, response): response.headers["x-request-id"] = request.id client = ReusableClient(app, port=1234) bad_headers = {"bad": "bad" * 5_000} with client: _, response1 = client.get("/") _, response2 = client.get("/", headers=bad_headers) assert response1.status == 200 assert response2.status == 413 assert (response1.headers["x-request-id"] != response2.headers["x-request-id"])
def test_keep_alive_server_timeout(): """If the client keep-alive timeout is longer than the server keep-alive timeout, the client will either a 'Connection reset' error _or_ a new connection. Depending on how the event-loop handles the broken server connection.""" loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) client = ReusableClient(keep_alive_app_server_timeout, loop=loop, port=PORT) with client: headers = {"Connection": "keep-alive"} request, response = client.get("/1", headers=headers, timeout=60) assert response.status == 200 assert response.text == "OK" assert request.protocol.state["requests_count"] == 1 loop.run_until_complete(aio_sleep(3)) request, response = client.get("/1", timeout=60) assert request.protocol.state["requests_count"] == 1
def runner(test_app): client = ReusableClient(test_app, port=PORT) client.run() yield client client.stop()