From 39124f8073dec0ba9b80076b882819578803035a Mon Sep 17 00:00:00 2001 From: Mario Leal Date: Wed, 7 Oct 2026 21:22:16 +0100 Subject: [PATCH] fix(mtls): a refused peer logs one warning, not an asyncio traceback Returning before super().connection_made() left uvicorn's inner protocol unset, so its connection_lost raised AttributeError on every refusal. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_015bTPg3qG72vYPLBigJks5h --- server/mtls.py | 6 ++++++ tests/test_mtls.py | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/server/mtls.py b/server/mtls.py index 5e267b6..4b49a5f 100644 --- a/server/mtls.py +++ b/server/mtls.py @@ -42,10 +42,16 @@ def make_protocol(allowed: frozenset[str]): transport.get_extra_info("peername"), uris or "none", ) + self._refused = True transport.abort() return super().connection_made(transport) + def connection_lost(self, exc): + if getattr(self, "_refused", False): # nothing was set up to tear down + return + super().connection_lost(exc) + return MTLSProtocol diff --git a/tests/test_mtls.py b/tests/test_mtls.py index e0faf28..629fea5 100644 --- a/tests/test_mtls.py +++ b/tests/test_mtls.py @@ -234,3 +234,11 @@ def test_renewed_cert_is_picked_up(pki, server): time.sleep(1.0) _, after = _get(pki, port, "core.bundle") assert before["serialNumber"] != after["serialNumber"] + + +def test_refusal_logs_no_traceback(pki, server, caplog): + """A refused peer is one warning line, not an asyncio callback traceback.""" + test_other_felt_identity_refused(pki, server) + time.sleep(0.3) + assert "is not allowed" in caplog.text + assert "Exception in callback" not in caplog.text