async def test_handle_end_body(stream: HTTPStream) -> None: stream.app_put = AsyncMock() await stream.handle(EndBody(stream_id=1)) stream.app_put.assert_called() assert stream.app_put.call_args_list == [ call({"type": "http.request", "body": b"", "more_body": False}) ]
async def test_send_reject(stream: WSStream) -> None: await stream.handle( Request( stream_id=1, http_version="2", headers=[(b"sec-websocket-version", b"13")], raw_path=b"/", method="GET", )) await stream.app_send( cast( WebsocketResponseStartEvent, { "type": "websocket.http.response.start", "status": 200, "headers": [] }, ), ) assert stream.state == ASGIWebsocketState.HANDSHAKE # Must wait for response before sending anything stream.send.assert_not_called() # type: ignore await stream.app_send( cast(WebsocketResponseBodyEvent, { "type": "websocket.http.response.body", "body": b"Body" })) assert stream.state == ASGIWebsocketState.HTTPCLOSED stream.send.assert_called() # type: ignore assert stream.send.call_args_list == [ # type: ignore call(Response(stream_id=1, headers=[], status_code=200)), call(Body(stream_id=1, data=b"Body")), call(EndBody(stream_id=1)), ] stream.config._log.access.assert_called() # type: ignore
async def test_send_response(stream: HTTPStream) -> None: await stream.handle( Request(stream_id=1, http_version="2", headers=[], raw_path=b"/?a=b", method="GET")) await stream.app_send( cast(HTTPResponseStartEvent, { "type": "http.response.start", "status": 200, "headers": [] })) assert stream.state == ASGIHTTPState.REQUEST # Must wait for response before sending anything stream.send.assert_not_called() # type: ignore await stream.app_send( cast(HTTPResponseBodyEvent, { "type": "http.response.body", "body": b"Body" })) assert stream.state == ASGIHTTPState.CLOSED stream.send.assert_called() # type: ignore assert stream.send.call_args_list == [ # type: ignore call(Response(stream_id=1, headers=[], status_code=200)), call(Body(stream_id=1, data=b"Body")), call(EndBody(stream_id=1)), call(StreamClosed(stream_id=1)), ] stream.config._log.access.assert_called() # type: ignore
async def test_protocol_handle_data_post_response( protocol: H11Protocol) -> None: await protocol.handle( RawData(data=b"POST / HTTP/1.1\r\nHost: hypercorn\r\n")) await protocol.stream_send( Response(stream_id=1, status_code=201, headers=[])) await protocol.stream_send(EndBody(stream_id=1)) await protocol.handle(RawData(data=b"abcd\r\n\r\n"))
async def test_protocol_handle_data_post_close(protocol: H11Protocol) -> None: await protocol.handle( RawData(data=b"POST / HTTP/1.1\r\nHost: hypercorn\r\nContent-Length: 10\r\n") ) await protocol.stream_send(Response(stream_id=1, status_code=201, headers=[])) await protocol.stream_send(EndBody(stream_id=1)) # Key is that this doesn't error await protocol.handle(RawData(data=b"abcdefghij"))
async def test_protocol_instant_recycle(protocol: H11Protocol) -> None: data = b"GET / HTTP/1.1\r\nHost: hypercorn\r\n\r\n" await protocol.handle(RawData(data=data)) assert protocol.stream is not None await protocol.stream_send(Response(stream_id=1, status_code=200, headers=[])) await protocol.stream_send(EndBody(stream_id=1)) await protocol.handle(RawData(data=data)) await protocol.stream_send(StreamClosed(stream_id=1)) # Should have recycled, i.e. a stream should exist assert protocol.stream is not None
async def test_protocol_send_stream_closed(keep_alive: bool, expected: Any, protocol: H11Protocol) -> None: data = b"GET / HTTP/1.1\r\nHost: hypercorn\r\n" if keep_alive: data += b"\r\n" else: data += b"Connection: close\r\n\r\n" await protocol.handle(RawData(data=data)) await protocol.stream_send( Response(stream_id=1, status_code=200, headers=[])) await protocol.stream_send(EndBody(stream_id=1)) await protocol.stream_send(StreamClosed(stream_id=1)) protocol.send.assert_called() assert protocol.send.call_args_list[2] == call(expected)
async def test_protocol_instant_recycle(protocol: H11Protocol) -> None: data = b"GET / HTTP/1.1\r\nHost: hypercorn\r\n\r\n" # This test requires a real event as the handling should pause on # the instant receipt protocol.can_read = EventWrapper() await protocol.handle(RawData(data=data)) assert protocol.stream is not None await protocol.stream_send( Response(stream_id=1, status_code=200, headers=[])) await protocol.stream_send(EndBody(stream_id=1)) task = asyncio.ensure_future(protocol.handle(RawData(data=data))) await asyncio.sleep(0) # Switch to task await protocol.stream_send(StreamClosed(stream_id=1)) # Should have recycled, i.e. a stream should exist assert protocol.stream is not None await asyncio.sleep(0) # Switch to task assert task.done()
async def test_protocol_handle_request(protocol: H11Protocol) -> None: client = h11.Connection(h11.CLIENT) await protocol.handle( RawData(data=client.send( h11.Request(method="GET", target="/?a=b", headers=BASIC_HEADERS)))) protocol.stream.handle.assert_called() assert protocol.stream.handle.call_args_list == [ call( Request( stream_id=1, headers=[(b"host", b"hypercorn"), (b"connection", b"close")], http_version="1.1", method="GET", raw_path=b"/?a=b", )), call(EndBody(stream_id=1)), ]
async def test_send_app_error(stream: HTTPStream) -> None: await stream.handle( Request(stream_id=1, http_version="2", headers=[], raw_path=b"/?a=b", method="GET") ) await stream.app_send(None) stream.send.assert_called() # type: ignore assert stream.send.call_args_list == [ # type: ignore call( Response( stream_id=1, headers=[(b"content-length", b"0"), (b"connection", b"close")], status_code=500, ) ), call(EndBody(stream_id=1)), call(StreamClosed(stream_id=1)), ] stream.config._log.access.assert_called() # type: ignore
async def test_protocol_handle_closed(protocol: H11Protocol) -> None: await protocol.handle( RawData( data= b"GET / HTTP/1.1\r\nHost: hypercorn\r\nConnection: close\r\n\r\n")) stream = protocol.stream await protocol.handle(Closed()) stream.handle.assert_called() assert stream.handle.call_args_list == [ call( Request( stream_id=1, headers=[(b"host", b"hypercorn"), (b"connection", b"close")], http_version="1.1", method="GET", raw_path=b"/", )), call(EndBody(stream_id=1)), call(StreamClosed(stream_id=1)), ]
async def test_invalid_server_name(stream: HTTPStream) -> None: stream.config.server_names = ["hypercorn"] await stream.handle( Request( stream_id=1, http_version="2", headers=[(b"host", b"example.com")], raw_path=b"/", method="GET", )) assert stream.send.call_args_list == [ # type: ignore call( Response( stream_id=1, headers=[(b"content-length", b"0"), (b"connection", b"close")], status_code=404, )), call(EndBody(stream_id=1)), ] # This shouldn't error await stream.handle(Body(stream_id=1, data=b"Body"))
async def test_send_app_error_handshake(stream: WSStream) -> None: await stream.handle( Request( stream_id=1, http_version="2", headers=[(b"sec-websocket-version", b"13")], raw_path=b"/", method="GET", )) await stream.app_send(None) stream.send.assert_called() assert stream.send.call_args_list == [ call( Response( stream_id=1, headers=[(b"content-length", b"0"), (b"connection", b"close")], status_code=500, )), call(EndBody(stream_id=1)), call(StreamClosed(stream_id=1)), ] stream.config._log.access.assert_called()
async def test_protocol_instant_recycle( protocol: H11Protocol, event_loop: asyncio.AbstractEventLoop) -> None: # This test task acts as the asgi app, spawned tasks act as the # server. data = b"GET / HTTP/1.1\r\nHost: hypercorn\r\n\r\n" # This test requires a real event as the handling should pause on # the instant receipt protocol.can_read = EventWrapper() task = event_loop.create_task(protocol.handle(RawData(data=data))) await asyncio.sleep(0) # Switch to task assert protocol.stream is not None assert task.done() await protocol.stream_send( Response(stream_id=1, status_code=200, headers=[])) await protocol.stream_send(EndBody(stream_id=1)) task = event_loop.create_task(protocol.handle(RawData(data=data))) await asyncio.sleep(0) # Switch to task await protocol.stream_send(StreamClosed(stream_id=1)) await asyncio.sleep(0) # Switch to task # Should have recycled, i.e. a stream should exist assert protocol.stream is not None assert task.done()