def test_unsupported_upgrade_request(protocol_cls, event_loop): app = Response("Hello, world", media_type="text/plain") with get_connected_protocol(app, protocol_cls, event_loop, ws="none") as protocol: protocol.data_received(UPGRADE_REQUEST) assert b"HTTP/1.1 400 Bad Request" in protocol.transport.buffer assert b"Unsupported upgrade request." in protocol.transport.buffer
def test_undersized_request(protocol_cls, event_loop): app = Response(b"xxx", headers={"content-length": "10"}) with get_connected_protocol(app, protocol_cls, event_loop) as protocol: protocol.data_received(SIMPLE_GET_REQUEST) protocol.loop.run_one() assert protocol.transport.is_closing()
def test_supported_upgrade_request(protocol_cls): app = Response("Hello, world", media_type="text/plain") protocol = get_connected_protocol(app, protocol_cls, ws="wsproto") protocol.data_received(UPGRADE_REQUEST) assert b"HTTP/1.1 426 " in protocol.transport.buffer
def test_invalid_http(protocol_cls): app = Response("Hello, world", media_type="text/plain") protocol = get_connected_protocol(app, protocol_cls) protocol.data_received(b"x" * 100000) assert protocol.transport.is_closing()
def test_shutdown_during_idle(protocol_cls, event_loop): app = Response("Hello, world", media_type="text/plain") with get_connected_protocol(app, protocol_cls, event_loop) as protocol: protocol.shutdown() assert protocol.transport.buffer == b"" assert protocol.transport.is_closing()
def test_oversized_request(protocol_cls): app = Response(b"xxx" * 20, headers={"content-length": "10"}) protocol = get_connected_protocol(app, protocol_cls) protocol.data_received(SIMPLE_GET_REQUEST) protocol.loop.run_one() assert protocol.transport.is_closing()
def test_head_request(protocol_cls, event_loop): app = Response("Hello, world", media_type="text/plain") with get_connected_protocol(app, protocol_cls, event_loop) as protocol: protocol.data_received(SIMPLE_HEAD_REQUEST) protocol.loop.run_one() assert b"HTTP/1.1 200 OK" in protocol.transport.buffer assert b"Hello, world" not in protocol.transport.buffer
def test_max_concurrency(protocol_cls): app = Response("Hello, world", media_type="text/plain") protocol = get_connected_protocol(app, protocol_cls, limit_concurrency=1) protocol.data_received(SIMPLE_GET_REQUEST) protocol.loop.run_one() assert b"HTTP/1.1 503 Service Unavailable" in protocol.transport.buffer
async def app(scope, receive, send): path = scope["path"] raw_path = scope.get("raw_path", None) assert "/one/two" == path assert b"/one%2Ftwo" == raw_path response = Response("Done", media_type="text/plain") await response(scope, receive, send)
def test_close(protocol_cls): app = Response(b"", status_code=204, headers={"connection": "close"}) protocol = get_connected_protocol(app, protocol_cls) protocol.data_received(SIMPLE_GET_REQUEST) protocol.loop.run_one() assert b"HTTP/1.1 204 No Content" in protocol.transport.buffer assert protocol.transport.is_closing()
def test_large_post_request(protocol_cls): app = Response("Hello, world", media_type="text/plain") protocol = get_connected_protocol(app, protocol_cls) protocol.data_received(LARGE_POST_REQUEST) assert protocol.transport.read_paused protocol.loop.run_one() assert not protocol.transport.read_paused
def test_early_response(protocol_cls): app = Response("Hello, world", media_type="text/plain") protocol = get_connected_protocol(app, protocol_cls) protocol.data_received(START_POST_REQUEST) protocol.loop.run_one() assert b"HTTP/1.1 200 OK" in protocol.transport.buffer protocol.data_received(FINISH_POST_REQUEST) assert not protocol.transport.is_closing()
async def __call__(self, receive, send): body = b"" more_body = True while more_body: message = await receive() body += message.get("body", b"") more_body = message.get("more_body", False) response = Response(b"Body: " + body, media_type="text/plain") await response(receive, send)
def test_get_request(protocol_cls): app = Response("Hello, world", media_type="text/plain") protocol = get_connected_protocol(app, protocol_cls) protocol.data_received(SIMPLE_GET_REQUEST) protocol.loop.run_one() assert b"HTTP/1.1 200 OK" in protocol.transport.buffer assert b"Hello, world" in protocol.transport.buffer
def test_shutdown_during_request(protocol_cls, event_loop): app = Response(b"", status_code=204) with get_connected_protocol(app, protocol_cls, event_loop) as protocol: protocol.data_received(SIMPLE_GET_REQUEST) protocol.shutdown() protocol.loop.run_one() assert b"HTTP/1.1 204 No Content" in protocol.transport.buffer assert protocol.transport.is_closing()
async def app( scope: Scope, receive: ASGIReceiveCallable, send: ASGISendCallable, ) -> None: scheme = scope["scheme"] # type: ignore host, port = scope["client"] # type: ignore addr = "%s://%s:%d" % (scheme, host, port) response = Response("Remote: " + addr, media_type="text/plain") await response(scope, receive, send)
def test_chunked_encoding_head_request(protocol_cls): app = Response(b"Hello, world!", status_code=200, headers={"transfer-encoding": "chunked"}) protocol = get_connected_protocol(app, protocol_cls) protocol.data_received(SIMPLE_HEAD_REQUEST) protocol.loop.run_one() assert b"HTTP/1.1 200 OK" in protocol.transport.buffer assert not protocol.transport.is_closing()
def test_invalid_http_request(request_line, protocol_cls, caplog, event_loop): app = Response("Hello, world", media_type="text/plain") request = INVALID_REQUEST_TEMPLATE % request_line caplog.set_level(logging.INFO, logger="uvicorn.error") logging.getLogger("uvicorn.error").propagate = True with get_connected_protocol(app, protocol_cls, event_loop) as protocol: protocol.data_received(request) assert b"HTTP/1.1 400 Bad Request" in protocol.transport.buffer assert b"Invalid HTTP request received." in protocol.transport.buffer
def test_invalid_http_request(request_line, protocol_cls, caplog): app = Response("Hello, world", media_type="text/plain") request = INVALID_REQUEST_TEMPLATE % request_line caplog.set_level(logging.INFO, logger="uvicorn.error") logging.getLogger("uvicorn.error").propagate = True protocol = get_connected_protocol(app, protocol_cls) protocol.data_received(request) assert not protocol.transport.buffer assert "Invalid HTTP request received." in caplog.messages
def test_chunked_encoding_empty_body(protocol_cls, event_loop): app = Response( b"Hello, world!", status_code=200, headers={"transfer-encoding": "chunked"} ) with get_connected_protocol(app, protocol_cls, event_loop) as protocol: protocol.data_received(SIMPLE_GET_REQUEST) protocol.loop.run_one() assert b"HTTP/1.1 200 OK" in protocol.transport.buffer assert protocol.transport.buffer.count(b"0\r\n\r\n") == 1 assert not protocol.transport.is_closing()
def test_keepalive_timeout(protocol_cls, event_loop): app = Response(b"", status_code=204) with get_connected_protocol(app, protocol_cls, event_loop) as protocol: protocol.data_received(SIMPLE_GET_REQUEST) protocol.loop.run_one() assert b"HTTP/1.1 204 No Content" in protocol.transport.buffer assert not protocol.transport.is_closing() protocol.loop.run_later(with_delay=1) assert not protocol.transport.is_closing() protocol.loop.run_later(with_delay=5) assert protocol.transport.is_closing()
def test_request_logging(path, protocol_cls, caplog): get_request_with_query_string = b"\r\n".join( ["GET {} HTTP/1.1".format(path).encode("ascii"), b"Host: example.org", b"", b""] ) caplog.set_level(logging.INFO, logger="uvicorn") app = Response("Hello, world", media_type="text/plain") protocol = get_connected_protocol(app, protocol_cls) protocol.data_received(get_request_with_query_string) protocol.loop.run_one() assert '"GET {} HTTP/1.1" 200'.format(path) in caplog.records[0].message
def test_fragmentation(): def receive_all(sock): chunks = [] while True: chunk = sock.recv(1024) if not chunk: break chunks.append(chunk) return b"".join(chunks) app = Response("Hello, world", media_type="text/plain") def send_fragmented_req(path): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(("127.0.0.1", 8000)) d = ( f"GET {path} HTTP/1.1\r\n" "Host: localhost\r\n" "Connection: close\r\n\r\n" ).encode() split = len(path) // 2 sock.sendall(d[:split]) time.sleep(0.01) sock.sendall(d[split:]) resp = receive_all(sock) # see https://github.com/kmonsoor/py-amqplib/issues/45 # we skip the error on bsd systems if python is too slow try: sock.shutdown(socket.SHUT_RDWR) except Exception: # pragma: no cover pass sock.close() return resp config = Config(app=app, http="httptools") server = Server(config=config) t = threading.Thread(target=server.run) t.daemon = True t.start() time.sleep(1) # wait for uvicorn to start path = "/?param=" + "q" * 10 response = send_fragmented_req(path) bad_response = b"HTTP/1.1 400 Bad Request" assert bad_response != response[: len(bad_response)] server.should_exit = True t.join()
def test_100_continue_not_sent_when_body_not_consumed(protocol_cls): app = Response(b"", status_code=204) protocol = get_connected_protocol(app, protocol_cls) EXPECT_100_REQUEST = b"\r\n".join([ b"POST / HTTP/1.1", b"Host: example.org", b"Expect: 100-continue", b"Content-Type: application/json", b"Content-Length: 18", b"", b'{"hello": "world"}', ]) protocol.data_received(EXPECT_100_REQUEST) protocol.loop.run_one() assert b"HTTP/1.1 100 Continue" not in protocol.transport.buffer assert b"HTTP/1.1 204 No Content" in protocol.transport.buffer
def app(scope): scheme = scope["scheme"] host, port = scope["client"] addr = "%s://%s:%d" % (scheme, host, port) return Response("Remote: " + addr, media_type="text/plain")
async def app(scope, receive, send): scheme = scope["scheme"] host, port = scope["client"] addr = "%s://%s:%d" % (scheme, host, port) response = Response("Remote: " + addr, media_type="text/plain") await response(scope, receive, send)
def app(scope): return Response("Hello, world", media_type="text/plain")
def app(scope): return Response(b"", status_code=204)
def app(scope): path = scope.get("root_path", "") + scope["path"] return Response("Path: " + path, media_type="text/plain")
def app(scope): content = "Version: %s" % scope["http_version"] return Response(content, media_type="text/plain")