From a13a68ed948ddec1e213c66d258d3b8447a4630e Mon Sep 17 00:00:00 2001 From: Val Date: Fri, 13 Feb 2026 13:56:38 +0100 Subject: [PATCH 1/2] revert default tcp_keep_alive --- lightbug_http/server.mojo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lightbug_http/server.mojo b/lightbug_http/server.mojo index ddeff7df..a3e0963c 100644 --- a/lightbug_http/server.mojo +++ b/lightbug_http/server.mojo @@ -477,7 +477,7 @@ struct Server(Movable): fn __init__( out self, var address: String = "127.0.0.1", - tcp_keep_alive: Bool = True, + tcp_keep_alive: Bool = False, ): self.config = ServerConfig() self._address = address^ @@ -487,7 +487,7 @@ struct Server(Movable): out self, var config: ServerConfig, var address: String = "127.0.0.1", - tcp_keep_alive: Bool = True, + tcp_keep_alive: Bool = False, ): self.config = config^ self._address = address^ From 98cb06277d653b1be0c47e77a696d45b8d7346bb Mon Sep 17 00:00:00 2001 From: Val Date: Fri, 13 Feb 2026 14:00:53 +0100 Subject: [PATCH 2/2] update tests --- tests/integration/integration_client.py | 19 +++++++++++++++++++ .../integration/integration_test_server.mojo | 2 +- tests/lightbug_http/test_server.mojo | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 tests/lightbug_http/test_server.mojo diff --git a/tests/integration/integration_client.py b/tests/integration/integration_client.py index a89366b1..30c3c249 100644 --- a/tests/integration/integration_client.py +++ b/tests/integration/integration_client.py @@ -1,3 +1,4 @@ +import concurrent.futures import requests import socket import time @@ -32,6 +33,24 @@ ) assert response.status_code == 200 +print("\n~~~ Testing parallel connections ~~~") +# Browsers open 6+ parallel connections for assets. +# A single-threaded server with keep-alive blocks on conn.read() waiting for +# the next request, preventing other connections from being accepted. +# This test verifies all parallel requests complete within a reasonable time. + + +def fetch(path): + return requests.get(f"http://127.0.0.1:8080{path}", headers={"connection": "close"}) + + +with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor: + futures = [executor.submit(fetch, f"/?n={i}") for i in range(4)] + results = concurrent.futures.wait(futures, timeout=5) + assert len(results.done) == 4, f"Only {len(results.done)}/4 parallel requests completed within 5s" + for f in results.done: + assert f.result().status_code == 200 + print("\n~~~ Testing content-length mismatch (smaller) ~~~") diff --git a/tests/integration/integration_test_server.mojo b/tests/integration/integration_test_server.mojo index b58e2af3..0c3b5ddc 100644 --- a/tests/integration/integration_test_server.mojo +++ b/tests/integration/integration_test_server.mojo @@ -37,6 +37,6 @@ struct IntegrationTestService(HTTPService): fn main() raises: - var server = Server(tcp_keep_alive=True) + var server = Server() var service = IntegrationTestService() server.listen_and_serve("127.0.0.1:8080", service) diff --git a/tests/lightbug_http/test_server.mojo b/tests/lightbug_http/test_server.mojo new file mode 100644 index 00000000..db4d6907 --- /dev/null +++ b/tests/lightbug_http/test_server.mojo @@ -0,0 +1,14 @@ +import testing +from lightbug_http.server import Server + + +def test_server_defaults_to_keep_alive_off(): + var server = Server() + testing.assert_false( + server.tcp_keep_alive, + "tcp_keep_alive must default to False for single-threaded server", + ) + + +def main(): + testing.TestSuite.discover_tests[__functions_in_module()]().run()