Read each request in full
read_request called recv once for the length and once for the body. A stream socket can deliver a request in several pieces, and the server then rejected that request. The server now uses the read loop of the client, which moves to utilities as recv_exact. The server refuses a request above 64 KiB.
This commit is contained in:
@@ -253,6 +253,46 @@ class TestReadRequestErrors:
|
||||
srv.close()
|
||||
cli.close()
|
||||
|
||||
@pytest.mark.parametrize("split", [2, 10], ids=["inside-the-length", "inside-the-body"])
|
||||
def test_request_in_two_pieces_is_read_whole(self, split):
|
||||
"""A stream socket can deliver one request in several pieces."""
|
||||
srv, cli = socket_module.socketpair(socket_module.AF_UNIX, socket_module.SOCK_STREAM)
|
||||
payload = json.dumps({"command": "GET", "client": "split"}).encode()
|
||||
frame = struct.pack("!I", len(payload)) + payload
|
||||
late = threading.Timer(0.05, cli.sendall, args=(frame[split:],))
|
||||
try:
|
||||
srv.settimeout(5)
|
||||
cli.sendall(frame[:split])
|
||||
late.start()
|
||||
assert read_request(srv) == {"command": "GET", "client": "split"}
|
||||
finally:
|
||||
late.join()
|
||||
srv.close()
|
||||
cli.close()
|
||||
|
||||
def test_client_that_closes_after_half_a_request_is_an_error(self):
|
||||
srv, cli = socket_module.socketpair(socket_module.AF_UNIX, socket_module.SOCK_STREAM)
|
||||
payload = json.dumps({"command": "GET", "client": "half"}).encode()
|
||||
try:
|
||||
cli.sendall(struct.pack("!I", len(payload)) + payload[:10])
|
||||
cli.close()
|
||||
with pytest.raises(OSError, match="unable to read socket: socket closed after 10 of"):
|
||||
read_request(srv)
|
||||
finally:
|
||||
srv.close()
|
||||
|
||||
def test_request_above_the_size_limit_is_refused(self):
|
||||
"""A wrong length prefix must not make the server wait for gigabytes."""
|
||||
from bmspy.server import MAX_REQUEST_BYTES
|
||||
srv, cli = socket_module.socketpair(socket_module.AF_UNIX, socket_module.SOCK_STREAM)
|
||||
try:
|
||||
cli.sendall(struct.pack("!I", MAX_REQUEST_BYTES + 1) + b"{}")
|
||||
with pytest.raises(OSError, match="exceeds the limit"):
|
||||
read_request(srv)
|
||||
finally:
|
||||
srv.close()
|
||||
cli.close()
|
||||
|
||||
def test_truncated_length_bytes_raises(self):
|
||||
srv, cli = socket_module.socketpair()
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user