From ac2c88629f548149def2c20868bfbee7744d558f Mon Sep 17 00:00:00 2001 From: Andrew Dang Date: Sat, 27 Jun 2026 01:57:58 -0500 Subject: [PATCH 1/2] Fix 503 request flags in unservicable connections --- cheroot/server.py | 7 ++++- cheroot/test/test_server.py | 58 +++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/cheroot/server.py b/cheroot/server.py index 284cf17c72..8149115f43 100644 --- a/cheroot/server.py +++ b/cheroot/server.py @@ -1893,7 +1893,12 @@ def _serve_unservicable(self): conn = self._unservicable_conns.get() if conn is _STOPPING_FOR_INTERRUPT: return - request = HTTPRequest(self, conn) + request = HTTPRequest( + self, + conn, + proxy_mode=self.proxy_mode, + strict_mode=self.strict_mode, + ) try: request.simple_response('503 Service Unavailable') except (OSError, errors.FatalSSLAlert): diff --git a/cheroot/test/test_server.py b/cheroot/test/test_server.py index ae6e390a44..d0bfad7915 100644 --- a/cheroot/test/test_server.py +++ b/cheroot/test/test_server.py @@ -127,6 +127,64 @@ def test_stop_interrupts_serve(): assert not serve_thread.is_alive() +def test_unservicable_conn_uses_server_proxy_and_strict_mode(monkeypatch): + """Check that 503 requests inherit proxy/strict mode from the server.""" + httpserver = HTTPServer( + bind_addr=(ANY_INTERFACE_IPV4, EPHEMERAL_PORT), + gateway=Gateway, + ) + close_calls = [] + request_init_args = [] + + class CapturingHTTPRequest: + """Capture request constructor args used for 503 responses.""" + + def __init__( + self, + server, + conn, + proxy_mode=False, + strict_mode=True, + ): + request_init_args.append( + { + 'server': server, + 'conn': conn, + 'proxy_mode': proxy_mode, + 'strict_mode': strict_mode, + }, + ) + + def simple_response(self, _status): + return None + + def close_conn(): + close_calls.append(None) + + conn = types.SimpleNamespace(linger=False, close=close_conn) + stopping_sentinel = object() + httpserver.proxy_mode = True + httpserver.strict_mode = False + httpserver.ready = True + httpserver._unservicable_conns.put(conn) + httpserver._unservicable_conns.put(stopping_sentinel) + monkeypatch.setattr('cheroot.server._STOPPING_FOR_INTERRUPT', stopping_sentinel) + monkeypatch.setattr('cheroot.server.HTTPRequest', CapturingHTTPRequest) + + httpserver._serve_unservicable() + + assert request_init_args == [ + { + 'server': httpserver, + 'conn': conn, + 'proxy_mode': True, + 'strict_mode': False, + }, + ] + assert conn.linger is True + assert close_calls == [None] + + @pytest.mark.parametrize( 'exc_cls', ( From a433c69696b5c00972539d12775abafa5a95b4d8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 27 Jun 2026 07:00:31 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- cheroot/test/test_server.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cheroot/test/test_server.py b/cheroot/test/test_server.py index d0bfad7915..b7286dafe5 100644 --- a/cheroot/test/test_server.py +++ b/cheroot/test/test_server.py @@ -168,7 +168,10 @@ def close_conn(): httpserver.ready = True httpserver._unservicable_conns.put(conn) httpserver._unservicable_conns.put(stopping_sentinel) - monkeypatch.setattr('cheroot.server._STOPPING_FOR_INTERRUPT', stopping_sentinel) + monkeypatch.setattr( + 'cheroot.server._STOPPING_FOR_INTERRUPT', + stopping_sentinel, + ) monkeypatch.setattr('cheroot.server.HTTPRequest', CapturingHTTPRequest) httpserver._serve_unservicable()